Skip to content

Commit 99c0bbf

Browse files
Pierre-Marie BatyExplorer09
authored andcommitted
FreeBSD: corrections to the used memory calculations
Resolves #1725
1 parent c21814e commit 99c0bbf

File tree

3 files changed

+53
-45
lines changed

3 files changed

+53
-45
lines changed

MemoryMeter.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,13 @@ static void MemoryMeter_display(const Object* cast, RichString* out) {
7878
RichString_appendAscii(out, CRT_colors[MEMORY_COMPRESSED], buffer);
7979
}
8080

81-
Meter_humanUnit(buffer, this->values[MEMORY_METER_BUFFERS], sizeof(buffer));
82-
RichString_appendAscii(out, settings->showCachedMemory ? CRT_colors[METER_TEXT] : CRT_colors[METER_SHADOW], " buffers:");
83-
RichString_appendAscii(out, settings->showCachedMemory ? CRT_colors[MEMORY_BUFFERS_TEXT] : CRT_colors[METER_SHADOW], buffer);
81+
/* 'buffers' memory field might be hidden by a setting in some OS
82+
ports (e.g. FreeBSD). */
83+
if (isNonnegative(this->values[MEMORY_METER_BUFFERS])) {
84+
Meter_humanUnit(buffer, this->values[MEMORY_METER_BUFFERS], sizeof(buffer));
85+
RichString_appendAscii(out, settings->showCachedMemory ? CRT_colors[METER_TEXT] : CRT_colors[METER_SHADOW], " buffers:");
86+
RichString_appendAscii(out, settings->showCachedMemory ? CRT_colors[MEMORY_BUFFERS_TEXT] : CRT_colors[METER_SHADOW], buffer);
87+
}
8488

8589
Meter_humanUnit(buffer, this->values[MEMORY_METER_CACHE], sizeof(buffer));
8690
RichString_appendAscii(out, settings->showCachedMemory ? CRT_colors[METER_TEXT] : CRT_colors[METER_SHADOW], " cache:");

freebsd/FreeBSDMachine.c

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@ static int MIB_vm_stats_vm_v_page_count[4];
4343

4444
static int MIB_vm_stats_vm_v_wire_count[4];
4545
static int MIB_vm_stats_vm_v_active_count[4];
46-
static int MIB_vm_stats_vm_v_cache_count[4];
46+
static int MIB_vm_stats_vm_v_laundry_count[4];
4747
static int MIB_vm_stats_vm_v_inactive_count[4];
48-
static int MIB_vm_stats_vm_v_free_count[4];
49-
static int MIB_vm_vmtotal[2];
5048

5149
static int MIB_vfs_bufspace[2];
5250

@@ -77,10 +75,8 @@ Machine* Machine_new(UsersTable* usersTable, uid_t userId) {
7775

7876
len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len);
7977
len = 4; sysctlnametomib("vm.stats.vm.v_active_count", MIB_vm_stats_vm_v_active_count, &len);
80-
len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len);
78+
len = 4; sysctlnametomib("vm.stats.vm.v_laundry_count", MIB_vm_stats_vm_v_laundry_count, &len);
8179
len = 4; sysctlnametomib("vm.stats.vm.v_inactive_count", MIB_vm_stats_vm_v_inactive_count, &len);
82-
len = 4; sysctlnametomib("vm.stats.vm.v_free_count", MIB_vm_stats_vm_v_free_count, &len);
83-
len = 2; sysctlnametomib("vm.vmtotal", MIB_vm_vmtotal, &len);
8480

8581
len = 2; sysctlnametomib("vfs.bufspace", MIB_vfs_bufspace, &len);
8682

@@ -310,65 +306,68 @@ static inline void FreeBSDMachine_scanCPU(Machine* super) {
310306
static void FreeBSDMachine_scanMemoryInfo(Machine* super) {
311307
FreeBSDMachine* this = (FreeBSDMachine*) super;
312308

313-
// @etosan:
314-
// memory counter relationships seem to be these:
315-
// total = active + wired + inactive + cache + free
316-
// htop_used (unavail to anybody) = active + wired + inactive - buffer
317-
// htop_cache (for cache meter) = buffer + cache
318-
// htop_user_free (avail to procs) = buffer + cache + free
319-
// htop_buffers (disk write buffer) = 0 (not applicable to FreeBSD)
309+
// comment by Pierre-Marie Baty <[email protected]>
320310
//
321-
// 'buffer' contain cache used by most file systems other than ZFS, and is
322-
// included in 'wired'
311+
// FreeBSD has the following memory classes:
312+
// active: userland pages currently mapped to physical memory (i.e. in use)
313+
// inactive: userland pages that are no longer active, can be (re)allocated to processes
314+
// laundry: userland pages that were just released, now being flushed, will become inactive
315+
// wired: kernel pages currently mapped to physical memory, cannot be paged out nor swapped
316+
// buffers: subcategory of 'wired' corresponding to the filesystem caches
317+
// free: pages that haven't been allocated yet, or have been released
323318
//
324-
// with ZFS ARC situation becomes bit muddled, as ARC behaves like "user_free"
325-
// and belongs into cache, but is reported as wired by kernel
319+
// htop has the following memory classes:
320+
// super->usedMem: can be mapped to FreeBSD's ('wired' - 'buffers') + 'laundry' + 'active'
321+
// super->buffersMem: can be mapped to FreeBSD's 'buffers'
322+
// super->cachedMem: can be mapped to FreeBSD's 'inactive'. Inactive pages are cached allocations.
326323
//
327-
// htop_used = active + (wired - arc)
328-
// htop_cache = buffers + cache + arc
324+
// With ZFS, the ARC area is NOT counted in the 'buffers' class, but is still counted in the 'wired'
325+
// class. The ARC total must thus be substracted from the 'wired' class AND added to the 'buffer' class,
326+
// so that the result (ARC being shown in buffersMem) is consistent with what ZFS users would expect.
327+
// This adjustment is done in Platform_setMemoryValues() in freebsd/Platform.c.
328+
329329
u_long totalMem;
330-
u_int memActive, memWire, memInactive, cachedMem;
330+
u_int memActive, memWire, memInactive, memLaundry;
331331
long buffersMem;
332332
size_t len;
333333
struct vmtotal vmtotal;
334334

335-
//disabled for now, as it is always smaller than phycal amount of memory...
336-
//...to avoid "where is my memory?" questions
337-
//sysctl(MIB_vm_stats_vm_v_page_count, 4, &(super->totalMem), &len, NULL, 0);
338-
//super->totalMem *= this->pageSizeKb;
335+
// total memory
339336
len = sizeof(totalMem);
340337
sysctl(MIB_hw_physmem, 2, &(totalMem), &len, NULL, 0);
341-
totalMem /= 1024;
342-
super->totalMem = totalMem;
338+
super->totalMem = totalMem / 1024;
343339

340+
// 'active' pages
344341
len = sizeof(memActive);
345342
sysctl(MIB_vm_stats_vm_v_active_count, 4, &(memActive), &len, NULL, 0);
346343
memActive *= this->pageSizeKb;
347344

345+
// 'wired' pages
348346
len = sizeof(memWire);
349347
sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(memWire), &len, NULL, 0);
350348
memWire *= this->pageSizeKb;
351349

350+
// 'inactive' pages
352351
len = sizeof(memInactive);
353352
sysctl(MIB_vm_stats_vm_v_inactive_count, 4, &(memInactive), &len, NULL, 0);
354353
memInactive *= this->pageSizeKb;
355354

355+
// 'laundry' pages
356+
len = sizeof(memLaundry);
357+
sysctl(MIB_vm_stats_vm_v_laundry_count, 4, &(memLaundry), &len, NULL, 0);
358+
memLaundry *= this->pageSizeKb;
359+
360+
// 'buffers' pages (separate read, should be deducted from 'wired')
356361
len = sizeof(buffersMem);
357362
sysctl(MIB_vfs_bufspace, 2, &(buffersMem), &len, NULL, 0);
358363
buffersMem /= 1024;
359-
super->cachedMem = buffersMem;
360-
361-
len = sizeof(cachedMem);
362-
sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(cachedMem), &len, NULL, 0);
363-
cachedMem *= this->pageSizeKb;
364-
super->cachedMem += cachedMem;
365-
366-
len = sizeof(vmtotal);
367-
sysctl(MIB_vm_vmtotal, 2, &(vmtotal), &len, NULL, 0);
368-
super->sharedMem = vmtotal.t_rmshr * this->pageSizeKb;
369364

370-
super->usedMem = memActive + memWire + memInactive - buffersMem;
365+
// now fill in the htop categories
366+
super->usedMem = (memWire - buffersMem) + memLaundry + memActive;
367+
super->cachedMem = memInactive;
368+
super->buffersMem = buffersMem;
371369

370+
// swap
372371
struct kvm_swap swap[16];
373372
int nswap = kvm_getswapinfo(this->kd, swap, ARRAYSIZE(swap), 0);
374373
super->totalSwap = 0;

freebsd/Platform.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,18 +243,23 @@ void Platform_setMemoryValues(Meter* this, double* totalUsed) {
243243
if (fhost->zfs.size > fhost->zfs.min)
244244
shrinkableSize = fhost->zfs.size - fhost->zfs.min;
245245
this->values[MEMORY_METER_USED] -= shrinkableSize;
246-
this->values[MEMORY_METER_CACHE] += shrinkableSize;
246+
this->values[MEMORY_METER_BUFFERS] += shrinkableSize;
247247
// this->values[MEMORY_METER_AVAILABLE] += shrinkableSize;
248248
}
249249

250250
*totalUsed = this->values[MEMORY_METER_USED];
251251
*totalUsed += this->values[MEMORY_METER_SHARED];
252252
// *totalUsed += this->values[MEMORY_METER_COMPRESSED];
253+
// In FreeBSD, 'buffers' memory is a subcategory of 'wired' and is
254+
// not reclaimable. It can be considered as 'used' as well.
255+
*totalUsed += this->values[MEMORY_METER_BUFFERS];
253256

254-
if (this->mode == BAR_METERMODE || this->mode == GRAPH_METERMODE) {
255-
Settings *settings = host->settings;
256-
if (!settings->showCachedMemory) {
257-
this->values[MEMORY_METER_BUFFERS] = 0;
257+
Settings *settings = host->settings;
258+
if (!settings->showCachedMemory) {
259+
this->values[MEMORY_METER_USED] += this->values[MEMORY_METER_BUFFERS];
260+
this->values[MEMORY_METER_BUFFERS] = NAN;
261+
262+
if (this->mode == BAR_METERMODE || this->mode == GRAPH_METERMODE) {
258263
this->values[MEMORY_METER_CACHE] = 0;
259264
}
260265
}

0 commit comments

Comments
 (0)