@@ -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,75 @@ 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, 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 ;
0 commit comments