Skip to content

Commit

Permalink
tools: add option --cgroupmap to profile.py
Browse files Browse the repository at this point in the history
  • Loading branch information
alban authored and yonghong-song committed Mar 18, 2020
1 parent 4c1136e commit f82ea45
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
11 changes: 9 additions & 2 deletions man/man8/profile.8
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.TH profile 8 "2016-07-17" "USER COMMANDS"
.TH profile 8 "2020-03-18" "USER COMMANDS"
.SH NAME
profile \- Profile CPU usage by sampling stack traces. Uses Linux eBPF/bcc.
.SH SYNOPSIS
.B profile [\-adfh] [\-p PID | \-L TID] [\-U | \-K] [\-F FREQUENCY | \-c COUNT]
.B [\-\-stack\-storage\-size COUNT] [duration]
.B [\-\-stack\-storage\-size COUNT] [\-\-cgroupmap CGROUPMAP] [duration]
.SH DESCRIPTION
This is a CPU profiler. It works by taking samples of stack traces at timed
intervals. It will help you understand and quantify CPU usage: which code is
Expand Down Expand Up @@ -62,6 +62,9 @@ The maximum number of unique stack traces that the kernel will count (default
\-C cpu
Collect stacks only from specified cpu.
.TP
\-\-cgroupmap MAPPATH
Profile cgroups in this BPF map only (filtered in-kernel).
.TP
duration
Duration to trace, in seconds.
.SH EXAMPLES
Expand Down Expand Up @@ -97,6 +100,10 @@ Profile for 5 seconds and output in folded stack format (suitable as input for f
Profile kernel stacks only:
#
.B profile -K
.TP
Profile a set of cgroups only (see filtering_by_cgroups.md from bcc sources for more details):
#
.B profile \-\-cgroupmap /sys/fs/bpf/test01
.SH DEBUGGING
See "[unknown]" frames with bogus addresses? This can happen for different
reasons. Your best approach is to get Linux perf to work first, and then to
Expand Down
19 changes: 19 additions & 0 deletions tools/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def stack_id_err(stack_id):
./profile -L 185 # only profile thread with TID 185
./profile -U # only show user space stacks (no kernel)
./profile -K # only show kernel space stacks (no user)
./profile --cgroupmap ./mappath # only trace cgroups in this BPF map
"""
parser = argparse.ArgumentParser(
description="Profile CPU stack traces at a timed interval",
Expand Down Expand Up @@ -112,6 +113,8 @@ def stack_id_err(stack_id):
help="cpu number to run profile on")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
parser.add_argument("--cgroupmap",
help="trace cgroups in this BPF map only")

# option logic
args = parser.parse_args()
Expand Down Expand Up @@ -143,6 +146,10 @@ def stack_id_err(stack_id):
BPF_HASH(counts, struct key_t);
BPF_STACK_TRACE(stack_traces, STACK_STORAGE_SIZE);
#if CGROUPSET
BPF_TABLE_PINNED("hash", u64, u64, cgroupset, 1024, "CGROUPPATH");
#endif
// This code gets a bit complex. Probably not suitable for casual hacking.
int do_perf_event(struct bpf_perf_event_data *ctx) {
Expand All @@ -156,6 +163,13 @@ def stack_id_err(stack_id):
if (!(THREAD_FILTER))
return 0;
#if CGROUPSET
u64 cgroupid = bpf_get_current_cgroup_id();
if (cgroupset.lookup(&cgroupid) == NULL) {
return 0;
}
#endif
// create map key
struct key_t key = {.pid = tgid};
bpf_get_current_comm(&key.name, sizeof(key.name));
Expand Down Expand Up @@ -232,6 +246,11 @@ def stack_id_err(stack_id):
stack_context = "user + kernel"
bpf_text = bpf_text.replace('USER_STACK_GET', user_stack_get)
bpf_text = bpf_text.replace('KERNEL_STACK_GET', kernel_stack_get)
if args.cgroupmap:
bpf_text = bpf_text.replace('CGROUPSET', '1')
bpf_text = bpf_text.replace('CGROUPPATH', args.cgroupmap)
else:
bpf_text = bpf_text.replace('CGROUPSET', '0')

sample_freq = 0
sample_period = 0
Expand Down
16 changes: 14 additions & 2 deletions tools/profile_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -703,12 +703,21 @@ WARNING: 8 stack traces could not be displayed. Consider increasing --stack-stor

Run ./profile -h to see the default.

The --cgroupmap option filters based on a cgroup set. It is meant to be used
with an externally created map.

# ./profile --cgroupmap /sys/fs/bpf/test01

For more details, see docs/filtering_by_cgroups.md


USAGE message:

# ./profile -h
usage: profile.py [-h] [-p PID | -L TID] [-U | -K] [-F FREQUENCY | -c COUNT] [-d] [-a]
[-I] [-f] [--stack-storage-size STACK_STORAGE_SIZE] [-C CPU]
usage: profile.py [-h] [-p PID | -L TID] [-U | -K] [-F FREQUENCY | -c COUNT]
[-d] [-a] [-I] [-f]
[--stack-storage-size STACK_STORAGE_SIZE] [-C CPU]
[--cgroupmap CGROUPMAP]
[duration]

Profile CPU stack traces at a timed interval
Expand Down Expand Up @@ -739,6 +748,8 @@ optional arguments:
the number of unique stack traces that can be stored
and displayed (default 16384)
-C CPU, --cpu CPU cpu number to run profile on
--cgroupmap CGROUPMAP
trace cgroups in this BPF map only

examples:
./profile # profile stack traces at 49 Hertz until Ctrl-C
Expand All @@ -750,3 +761,4 @@ examples:
./profile -L 185 # only profile thread with TID 185
./profile -U # only show user space stacks (no kernel)
./profile -K # only show kernel space stacks (no user)
./profile --cgroupmap ./mappath # only trace cgroups in this BPF map

0 comments on commit f82ea45

Please sign in to comment.