blob: f1911b094e08f98a95b320bd8ff78b04b686ed18 [file] [log] [blame]
Brendan Gregg203b4c92016-10-18 12:10:24 -07001#!/usr/bin/python
2# @lint-avoid-python-3-compatibility-imports
3#
4# slabratetop Summarize kmem_cache_alloc() calls.
5# For Linux, uses BCC, eBPF.
6#
7# USAGE: slabratetop [-h] [-C] [-r MAXROWS] [interval] [count]
8#
9# This uses in-kernel BPF maps to store cache summaries for efficiency.
10#
11# SEE ALSO: slabtop(1), which shows the cache volumes.
12#
13# Copyright 2016 Netflix, Inc.
14# Licensed under the Apache License, Version 2.0 (the "License")
15#
16# 15-Oct-2016 Brendan Gregg Created this.
17
18from __future__ import print_function
19from bcc import BPF
Brenden Blanco42d60982017-04-24 14:31:28 -070020from bcc.utils import printb
Brendan Gregg203b4c92016-10-18 12:10:24 -070021from time import sleep, strftime
22import argparse
23import signal
24from subprocess import call
25
26# arguments
27examples = """examples:
28 ./slabratetop # kmem_cache_alloc() top, 1 second refresh
29 ./slabratetop -C # don't clear the screen
30 ./slabratetop 5 # 5 second summaries
31 ./slabratetop 5 10 # 5 second summaries, 10 times only
32"""
33parser = argparse.ArgumentParser(
34 description="Kernel SLAB/SLUB memory cache allocation rate top",
35 formatter_class=argparse.RawDescriptionHelpFormatter,
36 epilog=examples)
37parser.add_argument("-C", "--noclear", action="store_true",
38 help="don't clear the screen")
39parser.add_argument("-r", "--maxrows", default=20,
40 help="maximum rows to print, default 20")
41parser.add_argument("interval", nargs="?", default=1,
42 help="output interval, in seconds")
43parser.add_argument("count", nargs="?", default=99999999,
44 help="number of outputs")
Nathan Scottcf0792f2018-02-02 16:56:50 +110045parser.add_argument("--ebpf", action="store_true",
46 help=argparse.SUPPRESS)
Brendan Gregg203b4c92016-10-18 12:10:24 -070047args = parser.parse_args()
48interval = int(args.interval)
49countdown = int(args.count)
50maxrows = int(args.maxrows)
51clear = not int(args.noclear)
52debug = 0
53
54# linux stats
55loadavg = "/proc/loadavg"
56
57# signal handler
58def signal_ignore(signal, frame):
59 print()
60
61# define BPF program
62bpf_text = """
63#include <uapi/linux/ptrace.h>
64#include <linux/mm.h>
65#include <linux/slab.h>
Gary Linfa103452018-03-14 18:14:56 +080066#ifdef CONFIG_SLUB
Brendan Gregg203b4c92016-10-18 12:10:24 -070067#include <linux/slub_def.h>
Gary Linfa103452018-03-14 18:14:56 +080068#else
69#include <linux/slab_def.h>
70#endif
Brendan Gregg203b4c92016-10-18 12:10:24 -070071
72#define CACHE_NAME_SIZE 32
73
74// the key for the output summary
75struct info_t {
76 char name[CACHE_NAME_SIZE];
77};
78
79// the value of the output summary
80struct val_t {
81 u64 count;
82 u64 size;
83};
84
85BPF_HASH(counts, struct info_t, struct val_t);
86
87int kprobe__kmem_cache_alloc(struct pt_regs *ctx, struct kmem_cache *cachep)
88{
89 struct info_t info = {};
90 bpf_probe_read(&info.name, sizeof(info.name), (void *)cachep->name);
91
92 struct val_t *valp, zero = {};
93 valp = counts.lookup_or_init(&info, &zero);
94 valp->count++;
95 valp->size += cachep->size;
96
97 return 0;
98}
99"""
Nathan Scottcf0792f2018-02-02 16:56:50 +1100100if debug or args.ebpf:
Brendan Gregg203b4c92016-10-18 12:10:24 -0700101 print(bpf_text)
Nathan Scottcf0792f2018-02-02 16:56:50 +1100102 if args.ebpf:
103 exit()
Brendan Gregg203b4c92016-10-18 12:10:24 -0700104
105# initialize BPF
106b = BPF(text=bpf_text)
107
108print('Tracing... Output every %d secs. Hit Ctrl-C to end' % interval)
109
110# output
111exiting = 0
112while 1:
113 try:
114 sleep(interval)
115 except KeyboardInterrupt:
116 exiting = 1
117
118 # header
119 if clear:
120 call("clear")
121 else:
122 print()
123 with open(loadavg) as stats:
124 print("%-8s loadavg: %s" % (strftime("%H:%M:%S"), stats.read()))
125 print("%-32s %6s %10s" % ("CACHE", "ALLOCS", "BYTES"))
126
127 # by-TID output
128 counts = b.get_table("counts")
129 line = 0
130 for k, v in reversed(sorted(counts.items(),
131 key=lambda counts: counts[1].size)):
Brenden Blanco42d60982017-04-24 14:31:28 -0700132 printb(b"%-32s %6d %10d" % (k.name, v.count, v.size))
Brendan Gregg203b4c92016-10-18 12:10:24 -0700133
134 line += 1
135 if line >= maxrows:
136 break
137 counts.clear()
138
139 countdown -= 1
140 if exiting or countdown == 0:
141 print("Detaching...")
142 exit()