Search code examples
linuxmemoryproc

What is the difference between smaps and smaps_rollup in linux


What is the difference between smaps and smaps_rollup in linux? I don't know why PSS size is different between the sum of smaps and smaps_rollup in all processes. I want to know how these commands get a PSS size.


Solution

  • When the Linux kernel calculates PSS (proportional set size), the kernel handles the value in the byte level (in practice, the kernel calculates PSS in much more fine-grained level. See below code snippet.). Here is a code snippet from smaps_account in /fs/proc/task_mmu.c:

        for (i = 0; i < nr; i++, page++) {
            int mapcount = page_mapcount(page);
            unsigned long pss = PAGE_SIZE << PSS_SHIFT;
            if (mapcount >= 2)
                pss /= mapcount;
            smaps_page_accumulate(mss, page, PAGE_SIZE, pss, dirty, locked,
                          mapcount < 2);
        }
    

    As you can see, to calculate pss for each page, the kernel divides the value by mapcount of the page before using it. So, the actual value can be represented in the byte-level. For example, if a page is mapped by three processes, each process gets 4KB/3 (1365.333 bytes) of pss size for this page.

    When users request to print /proc/<pid>/smaps, the kernel prints smaps for each vma in the target process while /proc/<pid>/smaps_rollup prints the sum of smaps. The problem is, the kernel prints values of /proc/<pid>/smaps (and also for /proc/<pid>/smaps_rollup) in KB. It means that PSS value under 1KB is discarded. See below code snippet. All printed values are right-shifted by 10.

    #define SEQ_PUT_DEC(str, val) \
            seq_put_decimal_ull_width(m, str, (val) >> 10, 8)
    
    /* Show the contents common for smaps and smaps_rollup */
    static void __show_smap(struct seq_file *m, const struct mem_size_stats *mss,
        bool rollup_mode)
    {
        SEQ_PUT_DEC("Rss:            ", mss->resident);
        SEQ_PUT_DEC(" kB\nPss:            ", mss->pss >> PSS_SHIFT);
        SEQ_PUT_DEC(" kB\nPss_Dirty:      ", mss->pss_dirty >> PSS_SHIFT);
        if (rollup_mode) {
            /*
             * These are meaningful only for smaps_rollup, otherwise two of
             * them are zero, and the other one is the same as Pss.
             */
            SEQ_PUT_DEC(" kB\nPss_Anon:       ",
                mss->pss_anon >> PSS_SHIFT);
            SEQ_PUT_DEC(" kB\nPss_File:       ",
                mss->pss_file >> PSS_SHIFT);
            SEQ_PUT_DEC(" kB\nPss_Shmem:      ",
                mss->pss_shmem >> PSS_SHIFT);
        }
    //...
    

    For /proc/<pid>/smaps_rollup, the kernel aggregates values in each smaps of vma including the discarded value under 1KB, then prints the value in KB. That's why the sum of PSS in smaps is differ from the PSS value in smaps_rollup.