@@ -43,9 +43,8 @@ static int MIB_vm_stats_vm_v_page_count[4];
4343
4444static int MIB_vm_stats_vm_v_wire_count [4 ];
4545static 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 ];
4747static int MIB_vm_stats_vm_v_inactive_count [4 ];
48- static int MIB_vm_stats_vm_v_free_count [4 ];
4948static int MIB_vm_vmtotal [2 ];
5049
5150static 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) {
310308static 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