Skip to content

Commit 2736ba0

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

2 files changed

Lines changed: 44 additions & 33 deletions

File tree

MemoryMeter.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ static void MemoryMeter_updateValues(Meter* this) {
5555
used += this->values[MEMORY_METER_SHARED];
5656
if (isPositive(this->values[MEMORY_METER_COMPRESSED]))
5757
used += this->values[MEMORY_METER_COMPRESSED];
58+
#if defined(__FreeBSD__)
59+
if (isPositive(this->values[MEMORY_METER_BUFFERS]))
60+
used += this->values[MEMORY_METER_BUFFERS];
61+
#endif // defined(__FreeBSD__)
5862

5963
written = Meter_humanUnit(buffer, used, size);
6064
METER_BUFFER_CHECK(buffer, size, written);

freebsd/FreeBSDMachine.c

Lines changed: 40 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,74 @@ 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 ARC, 'buffers' being a subset of 'wired', both these classes will grow in FreeBSD's 'top'.
328+
// In htop, since only the non-'buffers' part of 'wired' is counted as usedMem, the result is that
329+
// only the buffersMem category will grow, which is consistent with what ZFS users would expect.
330+
329331
u_long totalMem;
330-
u_int memActive, memWire, memInactive, cachedMem;
331-
long buffersMem;
332+
u_int memActive, memWire, memInactive, memLaundry;
333+
long buffersMem, sharedMem;
332334
size_t len;
333335
struct vmtotal vmtotal;
334336

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;
337+
// total memory
339338
len = sizeof(totalMem);
340339
sysctl(MIB_hw_physmem, 2, &(totalMem), &len, NULL, 0);
341-
totalMem /= 1024;
342-
super->totalMem = totalMem;
340+
super->totalMem = totalMem / 1024;
343341

342+
// 'active' pages
344343
len = sizeof(memActive);
345344
sysctl(MIB_vm_stats_vm_v_active_count, 4, &(memActive), &len, NULL, 0);
346345
memActive *= this->pageSizeKb;
347346

347+
// 'wired' pages
348348
len = sizeof(memWire);
349349
sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(memWire), &len, NULL, 0);
350350
memWire *= this->pageSizeKb;
351351

352+
// 'inactive' pages
352353
len = sizeof(memInactive);
353354
sysctl(MIB_vm_stats_vm_v_inactive_count, 4, &(memInactive), &len, NULL, 0);
354355
memInactive *= this->pageSizeKb;
355356

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

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

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

378+
// swap
372379
struct kvm_swap swap[16];
373380
int nswap = kvm_getswapinfo(this->kd, swap, ARRAYSIZE(swap), 0);
374381
super->totalSwap = 0;

0 commit comments

Comments
 (0)