From 86df2b8b562cb83152fc050d1eabd8dbd4302115 Mon Sep 17 00:00:00 2001 From: Teng Qin Date: Mon, 23 Apr 2018 12:36:51 -0700 Subject: [PATCH] Add -c option for profile.py --- man/man8/profile.8 | 11 +++++++++-- tools/profile.py | 26 +++++++++++++++++++++----- tools/profile_example.txt | 9 ++++++--- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/man/man8/profile.8 b/man/man8/profile.8 index fca31fd830f4..f44dd6896d6d 100644 --- a/man/man8/profile.8 +++ b/man/man8/profile.8 @@ -2,7 +2,7 @@ .SH NAME profile \- Profile CPU usage by sampling stack traces. Uses Linux eBPF/bcc. .SH SYNOPSIS -.B profile [\-adfh] [\-p PID] [\-U | \-k] [\-F FREQUENCY] +.B profile [\-adfh] [\-p PID] [\-U | \-K] [\-F FREQUENCY | \-c COUNT] .B [\-\-stack\-storage\-size COUNT] [duration] .SH DESCRIPTION This is a CPU profiler. It works by taking samples of stack traces at timed @@ -32,7 +32,10 @@ Trace this process ID only (filtered in-kernel). Without this, all CPUs are profiled. .TP \-F frequency -Frequency to sample stacks (default 49). +Frequency to sample stacks. +.TP +\-c count +Sample stacks every one in this many events. .TP \-f Print output in folded stack format. @@ -67,6 +70,10 @@ Profile at 99 Hertz for 5 seconds only: # .B profile -F 99 5 .TP +Profile 1 in a million events for 5 seconds only: +# +.B profile -c 1000000 5 +.TP Profile PID 181 only: # .B profile -p 181 diff --git a/tools/profile.py b/tools/profile.py index e804fb8e2620..1b26ce778ae5 100755 --- a/tools/profile.py +++ b/tools/profile.py @@ -63,6 +63,7 @@ def positive_nonzero_int(val): examples = """examples: ./profile # profile stack traces at 49 Hertz until Ctrl-C ./profile -F 99 # profile stack traces at 99 Hertz + ./profile -c 1000000 # profile stack traces every 1 in a million events ./profile 5 # profile at 49 Hertz for 5 seconds only ./profile -f 5 # output in folded format for flame graphs ./profile -p 185 # only profile threads for PID 185 @@ -82,8 +83,11 @@ def positive_nonzero_int(val): help="show stacks from user space only (no kernel space stacks)") stack_group.add_argument("-K", "--kernel-stacks-only", action="store_true", help="show stacks from kernel space only (no user space stacks)") -parser.add_argument("-F", "--frequency", type=positive_int, default=49, - help="sample frequency, Hertz (default 49)") +sample_group = parser.add_mutually_exclusive_group() +sample_group.add_argument("-F", "--frequency", type=positive_int, + help="sample frequency, Hertz") +sample_group.add_argument("-c", "--count", type=positive_int, + help="sample period, number of events") parser.add_argument("-d", "--delimited", action="store_true", help="insert delimiter between kernel/user stacks") parser.add_argument("-a", "--annotations", action="store_true", @@ -214,10 +218,22 @@ def positive_nonzero_int(val): bpf_text = bpf_text.replace('USER_STACK_GET', user_stack_get) bpf_text = bpf_text.replace('KERNEL_STACK_GET', kernel_stack_get) +sample_freq = 0 +sample_period = 0 +if args.frequency: + sample_freq = args.frequency +elif args.count: + sample_period = args.count +else: + # If user didn't specify anything, use default 49Hz sampling + sample_freq = 49 +sample_context = "%s%d %s" % (("", sample_freq, "Hertz") if sample_freq + else ("every ", sample_period, "events")) + # header if not args.folded: - print("Sampling at %d Hertz of %s by %s stack" % - (args.frequency, thread_context, stack_context), end="") + print("Sampling at %s of %s by %s stack" % + (sample_context, thread_context, stack_context), end="") if duration < 99999999: print(" for %d secs." % duration) else: @@ -232,7 +248,7 @@ def positive_nonzero_int(val): b = BPF(text=bpf_text) b.attach_perf_event(ev_type=PerfType.SOFTWARE, ev_config=PerfSWConfig.CPU_CLOCK, fn_name="do_perf_event", - sample_period=0, sample_freq=args.frequency) + sample_period=sample_period, sample_freq=sample_freq) # signal handler def signal_ignore(signal, frame): diff --git a/tools/profile_example.txt b/tools/profile_example.txt index 25f985412c41..efc648c2fd5f 100644 --- a/tools/profile_example.txt +++ b/tools/profile_example.txt @@ -704,8 +704,8 @@ Run ./profile -h to see the default. USAGE message: # ./profile -h -usage: profile [-h] [-p PID] [-U | -K] [-F FREQUENCY] [-d] [-a] [-f] - [--stack-storage-size STACK_STORAGE_SIZE] +usage: profile [-h] [-p PID] [-U | -K] [-F FREQUENCY | -c COUNT] [-d] [-a] + [-f] [--stack-storage-size STACK_STORAGE_SIZE] [duration] Profile CPU stack traces at a timed interval @@ -723,7 +723,9 @@ optional arguments: show stacks from kernel space only (no user space stacks) -F FREQUENCY, --frequency FREQUENCY - sample frequency, Hertz (default 49) + sample frequency, Hertz + -c COUNT, --count COUNT + sample period, number of events -d, --delimited insert delimiter between kernel/user stacks -a, --annotations add _[k] annotations to kernel frames -f, --folded output folded format, one line per stack (for flame @@ -735,6 +737,7 @@ optional arguments: examples: ./profile # profile stack traces at 49 Hertz until Ctrl-C ./profile -F 99 # profile stack traces at 99 Hertz + ./profile -c 1000000 # profile stack traces every 1 in a million events ./profile 5 # profile at 49 Hertz for 5 seconds only ./profile -f 5 # output in folded format for flame graphs ./profile -p 185 # only profile threads for PID 185