Skip to content

Commit

Permalink
stackcount: add -c option for CPU only events (iovisor#2307)
Browse files Browse the repository at this point in the history
Add the -c option to trace events happened only the requested CPU.
Update command line, man and example.

Signed-off-by: Dima Stepanov <[email protected]>
Signed-off-by: Yury Kotov <[email protected]>
  • Loading branch information
dstepanovsrc authored and yonghong-song committed Apr 10, 2019
1 parent fd73745 commit e75480d
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 13 deletions.
11 changes: 9 additions & 2 deletions man/man8/stackcount.8
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
.SH NAME
stackcount \- Count function calls and their stack traces. Uses Linux eBPF/bcc.
.SH SYNOPSIS
.B stackcount [\-h] [\-p PID] [\-i INTERVAL] [\-D DURATION] [\-T] [\-r] [\-s]
[\-P] [\-K] [\-U] [\-v] [\-d] [\-f] pattern
.B stackcount [\-h] [\-p PID] [\-c CPU] [\-i INTERVAL] [\-D DURATION] [\-T] [\-r]
[\-s] [\-P] [\-K] [\-U] [\-v] [\-d] [\-f] pattern
.SH DESCRIPTION
stackcount traces functions and frequency counts them with their entire
stack trace, kernel stack and user stack, summarized in-kernel for efficiency.
Expand Down Expand Up @@ -54,6 +54,9 @@ Folded output format.
\-p PID
Trace this process ID only (filtered in-kernel).
.TP
\-c CPU
Trace this CPU only (filtered in-kernel).
.TP
.TP
pattern
A function name, or a search pattern. Can include wildcards ("*"). If the
Expand Down Expand Up @@ -104,6 +107,10 @@ Only count stacks when PID 185 is on-CPU:
#
.B stackcount \-p 185 ip_output
.TP
Only count stacks for CPU 1:
#
.B stackcount \-c 1 put_prev_entity
.TP
Count user stacks for dynamic heap allocations with malloc in PID 185:
#
.B stackcount \-p 185 c:malloc
Expand Down
26 changes: 17 additions & 9 deletions tools/stackcount.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# stackcount Count events and their stack traces.
# For Linux, uses BCC, eBPF.
#
# USAGE: stackcount.py [-h] [-p PID] [-i INTERVAL] [-D DURATION] [-T] [-r] [-s]
# [-P] [-K] [-U] [-v] [-d] [-f] [--debug]
# USAGE: stackcount.py [-h] [-p PID] [-c CPU] [-i INTERVAL] [-D DURATION] [-T]
# [-r] [-s] [-P] [-K] [-U] [-v] [-d] [-f] [--debug]
#
# The pattern is a string with optional '*' wildcards, similar to file
# globbing. If you'd prefer to use regular expressions, use the -r option.
Expand All @@ -28,7 +28,7 @@

class Probe(object):
def __init__(self, pattern, kernel_stack, user_stack, use_regex=False,
pid=None, per_pid=False):
pid=None, per_pid=False, cpu=None):
"""Init a new probe.
Init the probe from the pattern provided by the user. The supported
Expand Down Expand Up @@ -75,6 +75,7 @@ def __init__(self, pattern, kernel_stack, user_stack, use_regex=False,

self.pid = pid
self.per_pid = per_pid
self.cpu = cpu
self.matched = 0

def is_kernel_probe(self):
Expand Down Expand Up @@ -149,14 +150,18 @@ def load(self):
BPF_STACK_TRACE(stack_traces, 1024);
"""

filter_text = []
# We really mean the tgid from the kernel's perspective, which is in
# the top 32 bits of bpf_get_current_pid_tgid().
if self.is_kernel_probe() and self.pid:
trace_count_text = trace_count_text.replace('FILTER',
('u32 pid; pid = bpf_get_current_pid_tgid() >> 32; ' +
'if (pid != %d) { return 0; }') % (self.pid))
else:
trace_count_text = trace_count_text.replace('FILTER', '')
filter_text.append('u32 pid; pid = bpf_get_current_pid_tgid() >> 32; ' +
'if (pid != %d) { return 0; }' % self.pid)

if self.is_kernel_probe() and self.cpu:
filter_text.append('struct task_struct *task; task = (struct task_struct*)bpf_get_current_task(); ' +
'if (task->cpu != %d) { return 0; }' % self.cpu)

trace_count_text = trace_count_text.replace('FILTER', '\n '.join(filter_text))

# We need per-pid statistics when tracing a user-space process, because
# the meaning of the symbols depends on the pid. We also need them if
Expand Down Expand Up @@ -211,6 +216,7 @@ def __init__(self):
./stackcount -r '^tcp_send.*' # same as above, using regular expressions
./stackcount -Ti 5 ip_output # output every 5 seconds, with timestamps
./stackcount -p 185 ip_output # count ip_output stacks for PID 185 only
./stackcount -c 1 put_prev_entity # count put_prev_entity stacks for CPU 1 only
./stackcount -p 185 c:malloc # count stacks for malloc in PID 185
./stackcount t:sched:sched_fork # count stacks for sched_fork tracepoint
./stackcount -p 185 u:node:* # count stacks for all USDT probes in node
Expand All @@ -223,6 +229,8 @@ def __init__(self):
epilog=examples)
parser.add_argument("-p", "--pid", type=int,
help="trace this PID only")
parser.add_argument("-c", "--cpu", type=int,
help="trace this CPU only")
parser.add_argument("-i", "--interval",
help="summary interval, seconds")
parser.add_argument("-D", "--duration",
Expand Down Expand Up @@ -271,7 +279,7 @@ def __init__(self):

self.probe = Probe(self.args.pattern,
self.kernel_stack, self.user_stack,
self.args.regexp, self.args.pid, self.args.perpid)
self.args.regexp, self.args.pid, self.args.perpid, self.args.cpu)
self.need_delimiter = self.args.delimited and not (
self.args.kernel_stacks_only or self.args.user_stacks_only)

Expand Down
6 changes: 4 additions & 2 deletions tools/stackcount_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -843,8 +843,8 @@ This folded output can be piped directly into flamegraph.pl (the Perl version).
USAGE message:

# ./stackcount -h
usage: stackcount [-h] [-p PID] [-i INTERVAL] [-D DURATION] [-T] [-r] [-s]
[-P] [-K] [-U] [-v] [-d] [-f] [--debug]
usage: stackcount [-h] [-p PID] [-c CPU] [-i INTERVAL] [-D DURATION] [-T] [-r]
[-s] [-P] [-K] [-U] [-v] [-d] [-f] [--debug]
pattern

Count events and their stack traces
Expand All @@ -855,6 +855,7 @@ positional arguments:
optional arguments:
-h, --help show this help message and exit
-p PID, --pid PID trace this PID only
-c CPU, --cpu CPU trace this CPU only
-i INTERVAL, --interval INTERVAL
summary interval, seconds
-D DURATION, --duration DURATION
Expand Down Expand Up @@ -886,5 +887,6 @@ examples:
./stackcount -p 185 c:malloc # count stacks for malloc in PID 185
./stackcount t:sched:sched_fork # count stacks for sched_fork tracepoint
./stackcount -p 185 u:node:* # count stacks for all USDT probes in node
./stackcount -c 1 put_prev_entity # count put_prev_entity stacks for CPU 1 only
./stackcount -K t:sched:sched_switch # kernel stacks only
./stackcount -U t:sched:sched_switch # user stacks only

0 comments on commit e75480d

Please sign in to comment.