Demonstrations of slabratetop, the Linux eBPF/bcc version.


slabratetop shows the rate of allocations and total bytes from the kernel
memory allocation caches (SLAB or SLUB), in a top-like display that refreshes.
For example:

# ./slabratetop
<screen clears>
07:01:35 loadavg: 0.38 0.21 0.12 1/342 13297

CACHE                            ALLOCS      BYTES
kmalloc-4096                       3554   14557184
kmalloc-256                        2382     609536
cred_jar                           2568     493056
anon_vma_chain                     2007     128448
anon_vma                            972      77760
sighand_cache                        24      50688
mm_struct                            49      50176
RAW                                  52      49920
proc_inode_cache                     59      38232
signal_cache                         24      26112
dentry                              135      25920
sock_inode_cache                     29      18560
files_cache                          24      16896
inode_cache                          13       7696
TCP                                   2       3840
pid                                  24       3072
sigqueue                             17       2720
ext4_inode_cache                      2       2160
buffer_head                          16       1664
xfs_trans                             5       1160

By default the screen refreshes every one second, and only the top 20 caches
are shown. These can be tuned with options: see USAGE (-h).

The output above showed that the kmalloc-4096 cache allocated the most, about
14 Mbytes during this interval. This is a generic cache; other caches have
more meaningful names ("dentry", "TCP", "pid", etc).

slabtop(1) is a similar tool that shows the current static volume and usage
of the caches. slabratetop shows the active call rates and total size of the
allocations.


Since "kmalloc-4096" isn't very descriptive, I'm interested in seeing the
kernel stacks that led to this allocation. In the future (maybe by now) the
bcc trace tool could do this. As I'm writing this, it can't, so I'll use my
older ftrace-based kprobe tool as a workarond. This is from my perf-tools
collection: https://github.com/brendangregg/perf-tools.

# ./perf-tools/bin/kprobe -s 'p:kmem_cache_alloc name=+0(+96(%di)):string' 'name == "kmalloc-4096' | head -100
Tracing kprobe kmem_cache_alloc. Ctrl-C to end.
          kprobe-3892  [002] d... 7888274.478331: kmem_cache_alloc: (kmem_cache_alloc+0x0/0x1b0) name="kmalloc-4096"
          kprobe-3892  [002] d... 7888274.478333: <stack trace>
 => kmem_cache_alloc
 => user_path_at_empty
 => vfs_fstatat
 => SYSC_newstat
 => SyS_newstat
 => entry_SYSCALL_64_fastpath
          kprobe-3892  [002] d... 7888274.478340: kmem_cache_alloc: (kmem_cache_alloc+0x0/0x1b0) name="kmalloc-4096"
          kprobe-3892  [002] d... 7888274.478341: <stack trace>
 => kmem_cache_alloc
 => user_path_at_empty
 => vfs_fstatat
 => SYSC_newstat
 => SyS_newstat
 => entry_SYSCALL_64_fastpath
          kprobe-3892  [002] d... 7888274.478345: kmem_cache_alloc: (kmem_cache_alloc+0x0/0x1b0) name="kmalloc-4096"
          kprobe-3892  [002] d... 7888274.478346: <stack trace>
 => kmem_cache_alloc
 => user_path_at_empty
 => vfs_fstatat
 => SYSC_newstat
 => SyS_newstat
 => entry_SYSCALL_64_fastpath
          kprobe-3892  [002] d... 7888274.478350: kmem_cache_alloc: (kmem_cache_alloc+0x0/0x1b0) name="kmalloc-4096"
          kprobe-3892  [002] d... 7888274.478351: <stack trace>
 => kmem_cache_alloc
 => user_path_at_empty
 => vfs_fstatat
 => SYSC_newstat
 => SyS_newstat
 => entry_SYSCALL_64_fastpath
          kprobe-3892  [002] d... 7888274.478355: kmem_cache_alloc: (kmem_cache_alloc+0x0/0x1b0) name="kmalloc-4096"
          kprobe-3892  [002] d... 7888274.478355: <stack trace>
 => kmem_cache_alloc
 => user_path_at_empty
 => vfs_fstatat
 => SYSC_newstat
 => SyS_newstat
 => entry_SYSCALL_64_fastpath
          kprobe-3892  [002] d... 7888274.478359: kmem_cache_alloc: (kmem_cache_alloc+0x0/0x1b0) name="kmalloc-4096"
          kprobe-3892  [002] d... 7888274.478359: <stack trace>
 => kmem_cache_alloc
 => user_path_at_empty
 => vfs_fstatat
 => SYSC_newstat
 => SyS_newstat
 => entry_SYSCALL_64_fastpath
[...]

This is just an example so that you can see it's possible to dig further.
Please don't copy-n-paste that kprobe command, as it's unlikely to work (the
"+0(+96(%di))" text is specific to a kernel version and architecture).

So these allocations are coming from user_path_at_empty(), which calls other
functions (not seen in the stack: I suspect it's a tail-call compiler
optimization).


USAGE:

# ./slabratetop -h
usage: slabratetop [-h] [-C] [-r MAXROWS] [interval] [count]

Kernel SLAB/SLUB memory cache allocation rate top

positional arguments:
  interval              output interval, in seconds
  count                 number of outputs

optional arguments:
  -h, --help            show this help message and exit
  -C, --noclear         don't clear the screen
  -r MAXROWS, --maxrows MAXROWS
                        maximum rows to print, default 20

examples:
    ./slabratetop            # kmem_cache_alloc() top, 1 second refresh
    ./slabratetop -C         # don't clear the screen
    ./slabratetop 5          # 5 second summaries
    ./slabratetop 5 10       # 5 second summaries, 10 times only
