Search code examples
memory-managementlinux-kernelprocfs

What is the reason for the discrepancy between /proc/[pid]/status:RssAnon and /proc/[pid]/smaps_rollup:Anonymous?


I regularly notice discrepancies between the numbers given for RssAnon in /proc/[pid]/status and for Anonymous in /proc/[pid]/smaps_rollup. I also looked at RssShmem in /proc/[pid]/status, but that did not help to explain the difference. For example:

status:Name: tail
status:RssAnon:          72 kB
status:RssShmem:          0 kB

smaps_rollup:Anonymous:  92 kB

In the system that I analyse (which has a 4.14 kernel), such discrepancies are common. There are also cases where the numbers match, but this is not quite as common.

I found a lot of pages where the contents of /proc/[pid]/status, /proc/[pid]/smaps and /proc/[pid]/smaps_rollup are explained. There was, however, never a conclusive explanation for the difference. An answer from rr- came closest (actually, statm and smaps were discussed here): https://stackoverflow.com/a/30799817/5747415, as it was based on the analysis of the kernel code for the generation of smaps and statm. It ended with a (plausible, but unconfirmed) assumption that smaps calculates its data in a reliable but time-consuming way by actually iterating over the memory regions, whereas the information in statm is based on counters (in this case MM_ANONPAGES) that are continuously updated at lots of different places - which might lead to inconsistencies.

Can someone provide some founded explanation for the discrepancies? Are they intended and the meaning of the values is different? Or is it actually a bug? Thanks a lot in advance.


Solution

  • The plausible theory you mention is true. The man pages have been updated: https://www.spinics.net/lists/linux-mm/msg230450.html

    Since 34e55232e59f7b19050267a05ff1226e5cd122a5 (introduced back in v2.6.34), Linux uses per-thread RSS counters to reduce cache contention on the per-mm counters. With a 4K page size, that means that you can end up with the counters off by up to 252KiB* per thread.

    (*this precise number is not strictly accurate, see thread for details)