Skip to content

Commit 0e60ca3

Browse files
Pierre-Marie Batynatoscott
authored andcommitted
FreeBSD: corrections to the used memory calculations
Resolves #1725
1 parent 8a87d3e commit 0e60ca3

3 files changed

Lines changed: 48 additions & 34 deletions

File tree

MemoryMeter.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ static void MemoryMeter_updateValues(Meter* this) {
4141
this->values[MEMORY_METER_AVAILABLE] = NAN;
4242
Platform_setMemoryValues(this);
4343
if ((this->mode == GRAPH_METERMODE || this->mode == BAR_METERMODE) && !settings->showCachedMemory) {
44+
#if !defined(HTOP_FREEBSD)
4445
this->values[MEMORY_METER_BUFFERS] = 0;
46+
#endif // !defined(HTOP_FREEBSD)
4547
this->values[MEMORY_METER_CACHE] = 0;
4648
}
4749
/* Do not print available memory in bar mode */
@@ -55,6 +57,10 @@ static void MemoryMeter_updateValues(Meter* this) {
5557
used += this->values[MEMORY_METER_SHARED];
5658
if (isPositive(this->values[MEMORY_METER_COMPRESSED]))
5759
used += this->values[MEMORY_METER_COMPRESSED];
60+
#if defined(HTOP_FREEBSD)
61+
if (isPositive(this->values[MEMORY_METER_BUFFERS]))
62+
used += this->values[MEMORY_METER_BUFFERS];
63+
#endif // defined(HTOP_FREEBSD)
5864

5965
written = Meter_humanUnit(buffer, used, size);
6066
METER_BUFFER_CHECK(buffer, size, written);

freebsd/FreeBSDMachine.c

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +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];
4948
static int MIB_vm_vmtotal[2];
5049

5150
static int MIB_vfs_bufspace[2];
@@ -77,9 +76,8 @@ Machine* Machine_new(UsersTable* usersTable, uid_t userId) {
7776

7877
len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len);
7978
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);
79+
len = 4; sysctlnametomib("vm.stats.vm.v_laundry_count", MIB_vm_stats_vm_v_laundry_count, &len);
8180
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);
8381
len = 2; sysctlnametomib("vm.vmtotal", MIB_vm_vmtotal, &len);
8482

8583
len = 2; sysctlnametomib("vfs.bufspace", MIB_vfs_bufspace, &len);
@@ -310,65 +308,75 @@ static inline void FreeBSDMachine_scanCPU(Machine* super) {
310308
static void FreeBSDMachine_scanMemoryInfo(Machine* super) {
311309
FreeBSDMachine* this = (FreeBSDMachine*) super;
312310

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)
311+
// comment by Pierre-Marie Baty <pm@pmbaty.com>
320312
//
321-
// 'buffer' contain cache used by most file systems other than ZFS, and is
322-
// included in 'wired'
313+
// FreeBSD has the following memory classes:
314+
// active: userland pages currently mapped to physical memory (i.e. in use)
315+
// inactive: userland pages that are no longer active, can be (re)allocated to processes
316+
// laundry: userland pages that were just released, now being flushed, will become inactive
317+
// wired: kernel pages currently mapped to physical memory, cannot be paged out nor swapped
318+
// buffers: subcategory of 'wired' corresponding to the filesystem caches
319+
// free: pages that haven't been allocated yet, or have been released
323320
//
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
321+
// htop has the following memory classes:
322+
// super->usedMem: can be mapped to FreeBSD's ('wired' - 'buffers') + 'laundry' + ('active' - shared)
323+
// super->buffersMem: can be mapped to FreeBSD's 'buffers'
324+
// super->cachedMem: can be mapped to FreeBSD's 'inactive'. Inactive pages are cached allocations.
325+
// super->sharedMem: must be read separately and deduced from the 'active' set
326326
//
327-
// htop_used = active + (wired - arc)
328-
// htop_cache = buffers + cache + arc
327+
// With ZFS, the ARC area is NOT counted in the 'buffers' class, but is still counted in the 'wired'
328+
// class. The ARC total must thus be substracted from the 'wired' class AND added to the 'buffer' class,
329+
// so that the result (ARC being shown in buffersMem) is consistent with what ZFS users would expect.
330+
// This adjustment is done in Platform_setMemoryValues() in freebsd/Platform.c.
331+
329332
u_long totalMem;
330-
u_int memActive, memWire, memInactive, cachedMem;
331-
long buffersMem;
333+
u_int memActive, memWire, memInactive, memLaundry;
334+
long buffersMem, sharedMem;
332335
size_t len;
333336
struct vmtotal vmtotal;
334337

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;
338+
// total memory
339339
len = sizeof(totalMem);
340340
sysctl(MIB_hw_physmem, 2, &(totalMem), &len, NULL, 0);
341-
totalMem /= 1024;
342-
super->totalMem = totalMem;
341+
super->totalMem = totalMem / 1024;
343342

343+
// 'active' pages
344344
len = sizeof(memActive);
345345
sysctl(MIB_vm_stats_vm_v_active_count, 4, &(memActive), &len, NULL, 0);
346346
memActive *= this->pageSizeKb;
347347

348+
// 'wired' pages
348349
len = sizeof(memWire);
349350
sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(memWire), &len, NULL, 0);
350351
memWire *= this->pageSizeKb;
351352

353+
// 'inactive' pages
352354
len = sizeof(memInactive);
353355
sysctl(MIB_vm_stats_vm_v_inactive_count, 4, &(memInactive), &len, NULL, 0);
354356
memInactive *= this->pageSizeKb;
355357

358+
// 'laundry' pages
359+
len = sizeof(memLaundry);
360+
sysctl(MIB_vm_stats_vm_v_laundry_count, 4, &(memLaundry), &len, NULL, 0);
361+
memLaundry *= this->pageSizeKb;
362+
363+
// 'buffers' pages (separate read, should be deduced from 'wired')
356364
len = sizeof(buffersMem);
357365
sysctl(MIB_vfs_bufspace, 2, &(buffersMem), &len, NULL, 0);
358366
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;
365367

368+
// 'shared' pages (separate read, should be deduced from 'active')
366369
len = sizeof(vmtotal);
367370
sysctl(MIB_vm_vmtotal, 2, &(vmtotal), &len, NULL, 0);
368-
super->sharedMem = vmtotal.t_rmshr * this->pageSizeKb;
371+
sharedMem = vmtotal.t_rmshr * this->pageSizeKb;
369372

370-
super->usedMem = memActive + memWire + memInactive - buffersMem;
373+
// now fill in the htop categories
374+
super->usedMem = (memWire - buffersMem) + memLaundry + (memActive - sharedMem);
375+
super->cachedMem = memInactive;
376+
super->buffersMem = buffersMem;
377+
super->sharedMem = sharedMem;
371378

379+
// swap
372380
struct kvm_swap swap[16];
373381
int nswap = kvm_getswapinfo(this->kd, swap, ARRAYSIZE(swap), 0);
374382
super->totalSwap = 0;

freebsd/Platform.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ void Platform_setMemoryValues(Meter* this) {
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
}

0 commit comments

Comments
 (0)