R C-R wrote:
But it is something else. To see why, consider a room in a hotel used for business meetings. The room has 200 seats in it. A meeting begins. I assume you would agree that the amount of seating space currently used for the meeting is 200 seats, right?
20 people attend the meeting. This is not somehow another measure of the current seating space, just of how many of its seats currently are occupied.
It is the same with "Swap used." Like with seating space, it is the amount of disk space currently used but it isn't necessarily the number of pages currently filled.
? Swap used is 20 seats and the available swap space is 180 seats. That is shown by the output of sysctl
$ sysctl vm.swapusage
vm.swapusage: total = 1024.00M used = 543.50M free = 480.50M
1024 seats available, 543.5 used, 480.5 free. My idea is that the "page ins" and "page outs" numbers in Activity Monitor are giving out misleading informations. Why?
Let's take "Page outs" for example. It is the same exact number of "Pageouts" in vm_stat output multiplied by the page size (4KB). The same for "Page ins". That IMVHO is wrong because the "Pageouts" and "Pageins" in the code are counters that keep getting incremented by 1 by the pagers. vm_stat just prints those numbers. This is the code section for printing the current values (not reiterating):
snapshot(void)
{
get_stats(&vm_stat);
printf("Mach Virtual Memory Statistics: (page size of %d bytes)\n",
(int) (pageSize));
sspstat("Pages free:", (uint64_t) (vm_stat.free_count - vm_stat.speculative_count));
sspstat("Pages active:", (uint64_t) (vm_stat.active_count));
sspstat("Pages inactive:", (uint64_t) (vm_stat.inactive_count));
sspstat("Pages speculative:", (uint64_t) (vm_stat.speculative_count));
sspstat("Pages wired down:", (uint64_t) (vm_stat.wire_count));
sspstat("\"Translation faults\":", (uint64_t) (vm_stat.faults));
sspstat("Pages copy-on-write:", (uint64_t) (vm_stat.cow_faults));
sspstat("Pages zero filled:", (uint64_t) (vm_stat.zero_fill_count));
sspstat("Pages reactivated:", (uint64_t) (vm_stat.reactivations));
sspstat("Pageins:", (uint64_t) (vm_stat.pageins));
sspstat("Pageouts:", (uint64_t) (vm_stat.pageouts));
#if defined(__ppc__) /* vm_statistics are still 32-bit on ppc */
printf("Object cache: %u hits of %u lookups (%u%% hit rate)\n",
#else
printf("Object cache: %llu hits of %llu lookups (%u%% hit rate)\n",
#endif
vm_stat.hits, vm_stat.lookups, percent);
}
vm_stat.pageouts gets incremented only once in the module vm_pageouts.c (the default pager) by the VM_STAT_INCR() macro:
if (page_list[entry].dirty) {
VM_STAT_INCR(pageouts);
DTRACE_VM2(pgout, int, 1, (uint64_t *), NULL);
pgpgout_count++;
}
Please note as an additional pgpgout_count (pages paged out) counter is present.
Now, I am not able to catch where the so called "swap used" value gets updated (the source code is much bigger than what I thought). What I know is that the Universal Page List can mark as clean some dirty pages adjacent to the original one requested to be paged out, and flush them all together as a cluster of pages to the backing store (so paged out, swapped out, whatever. They are used by many as interchangeable terms in this contest) still keeping the copy of some of these pages in RAM. These pages increment the used backing store size but not the pageouts counter. Which is 1 for for each cluster of pages flushed to disk.
This would be a sort of cache (again). But since those pages are inactive and clean they would be the first to go (without the need to page them out again. They are marked clean) if free memory is needed before they get reused (and so put in the inactive list) if ever. Let's say, as usual, it would optimize I/O performances.
This would explain why the number of pages swapped out in the backing store (= swap used / page size) is superior to the pageouts counter at the beginning of the first paging out activity. But yet again it wouldn't give the answer to the original questions of this discussion.