-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generalize stackcount to support uprobes and tracepoints #580
Comments
Looks good to me. At some point we'll have the BPF_PROG_TYPE_TRACEPOINT support in bcc, so tracepoints should get easier. |
Now that we really have tracepoint support, it's actually harder than it seems because we don't have the By the way, the same considerations apply to
@brendangregg: What do you think? |
wait a sec. get_stackid() should be working as-is for tracepoints. |
Check it out: stacks from tracepoints: # ./urandomread-test.py
TIME(s) COMM PID GOTBITS
23459954.705288000 dd 20943 8192
23459954.705396000 dd 20943 8192
23459954.705497999 dd 20943 8192
23459954.705635000 dd 20943 8192
23459954.705745999 dd 20943 8192
^C urandom_read
__vfs_read
vfs_read
sys_read
entry_SYSCALL_64_fastpath
5 Program #!/usr/bin/python
#
# urandomread-stacks Example of instrumenting a kernel tracepoint.
# For Linux, uses BCC, BPF. Embedded C.
#
# REQUIRES: Linux 4.7+ (BPF_PROG_TYPE_TRACEPOINT support).
#
# Test by running this, then in another shell, run:
# dd if=/dev/urandom of=/dev/null bs=1k count=5
#
# Copyright 2016 Netflix, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
from __future__ import print_function
from bcc import BPF
import signal
# load BPF program
b = BPF(text="""
BPF_HASH(counts, int);
BPF_STACK_TRACE(stack_traces, 1024)
TRACEPOINT_PROBE(random, urandom_read) {
// args is from /sys/kernel/debug/tracing/events/random/urandom_read/format
int key = stack_traces.get_stackid(args, BPF_F_REUSE_STACKID);
u64 zero = 0;
u64 *val = counts.lookup_or_init(&key, &zero);
(*val)++;
bpf_trace_printk("%d\\n", args->got_bits);
return 0;
};
""")
# header
print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "GOTBITS"))
# print stacks on Ctrl-C
def print_stacks(signal, frame):
counts = b["counts"]
stack_traces = b["stack_traces"]
for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
for addr in stack_traces.walk(k.value):
print(" %s" % b.ksym(addr))
print(" %d\n" % v.value)
exit()
signal.signal(signal.SIGINT, print_stacks)
# format output
while 1:
try:
(task, pid, cpu, flags, ts, msg) = b.trace_fields()
except ValueError:
continue
print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg)) So I just used args as ctx, and it worked. @goldshtn not sure about library switches (-l), since the precedent is to use prefixes on the probe name directly. |
@4ast: I just assumed it wouldn't work. Very happy to learn that it does. Sorry :) @brendangregg: OK, sounds reasonable. There are a couple of prerequisites to make it happen, namely need to support uprobe, tracepoint, and USDT attach with regex. |
@brendangregg @4ast
TIME(s) COMM PID GOTBITS |
Currently,
stackcount
supports only kernel functions. It is a fairly low-hanging fruit to add user functions by using uprobes instead of kprobes. It should also be quite easy to add tracepoint support (using the current hacky approach or waiting for the 4.7 native support) and USDT probes as well.I think in a lot of cases,
stackcount
on one of these data sources can replace more specialised tools. For example, if I want to know where my threads are blocked for mutexes, I'd use thepthread_mutex_lock
USDT probe (or a uprobe on that function). If I want to know where threads are issuing a lot of block I/Os, I'd use theblock:block_rq_issue
tracepoint. And so on.There's the more-or-less uniform syntax currently used by
argdist
andtrace
that I propose to use here as well. Something like this:What do you think?
/cc @brendangregg
The text was updated successfully, but these errors were encountered: