profile(8)

πŸ“¦ version 0.36.1, in centos-stream 10, centos-stream 9, fedora 43, fedora 44

πŸŽ€ NAME πŸŽ€

profile(8), from the System Manager's Manual, is a CPU profiler that samples stack traces. It runs on Linux eBPF/bcc πŸ’œ


✨ SYNOPSIS ✨

profile [-adfh] [-p PID | -L TID] [-U | -K] [-F FREQUENCY | -c COUNT]
[--stack-storage-size COUNT] [-C CPU] [--cgroupmap CGROUPMAP]
[--mntnsmap MAPPATH] [duration]

πŸ’… DESCRIPTION πŸ’…

okay so this is a CPU profiler, bestie 😭 It takes samples of stack traces at timed intervals, so you can see exactly what's eating your CPU: which code is running and how much of it. That covers both user-level and kernel code, no cap πŸ”₯

By default it samples at 49 Hertz (samples per second) across all CPUs. You can tune that with a command line option ✨ The reason it's 49 and not 50 is to avoid lock-step sampling, which is very smart and very iconic 🧠

It's also super efficient πŸ¦‹ Stack traces get frequency counted in kernel context instead of being passed to user space for counting. Only the unique stacks and their counts get sent to user space at the end of the profile, so the kernel<->user transfer is greatly reduced. It's giving performance πŸ’–


🧚 REQUIREMENTS 🧚

You need CONFIG_BPF and bcc 🌸

This also requires Linux 4.9+ (BPF_PROG_TYPE_PERF_EVENT support). If you're on something older, check out tools/old, which is an older version that may work on Linux 4.6 - 4.8 πŸ₯Ί


πŸŽ€ OPTIONS πŸŽ€

  • -h β€” Prints the usage message πŸ’…
  • -p PID β€” Only traces the process with one or more comma separated PIDs (filtered in-kernel) πŸ¦‹
  • -L TID β€” Only traces the thread with one or more comma separated TIDs (filtered in-kernel) 🧡
  • -F frequency β€” The frequency at which stacks get sampled ⏱️
  • -c count β€” Samples stacks once every this many events 🎯
  • -f β€” Prints the output in folded stack format πŸ₯ž
  • -d β€” Adds an output delimiter between kernel and user stacks (either --, or, in folded mode, -) βœ‚οΈ
  • -U β€” Shows stacks from user space only, so no kernel space stacks πŸ‘‘
  • -K β€” Shows stacks from kernel space only, so no user space stacks 🧠
  • -I β€” Includes CPU idle stacks. By default these are excluded, so this one is for the idle-curious 😴
  • --stack-storage-size COUNT β€” The max number of unique stack traces the kernel will count (default 16384). If the sampled count goes over that, a warning gets printed ⚠️
  • -C cpu β€” Collects stacks only from the specified CPU 🎯
  • --cgroupmap MAPPATH β€” Profiles cgroups in this BPF map only (filtered in-kernel) 🌈
  • duration β€” How long to trace, in seconds ⏳

πŸ“ EXAMPLES πŸ“

Profile (sample) stack traces system-wide at 49 Hertz (samples per second) until you hit Ctrl-C:

# profile

Profile for 5 seconds only:

# profile 5

Profile at 99 Hertz for 5 seconds only:

# profile -F 99 5

Profile 1 in a million events for 5 seconds only:

# profile -c 1000000 5

Profile the process with PID 181 only:

# profile -p 181

Profile the thread with TID 181 only:

# profile -L 181

Profile for 5 seconds and output in folded stack format (perfect as input for flame graphs), including a delimiter between kernel and user stacks:

# profile -df 5

Profile kernel stacks only:

# profile -K

Profile a set of cgroups only (see special_filtering.md from bcc sources for more details):

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

πŸ™ˆ DEBUGGING πŸ™ˆ

Seeing "[unknown]" frames with bogus addresses? πŸ’€ This can happen for different reasons. Your best move is to get Linux perf working first, and then try this tool. For example, "perf record -F 49 -a -g -- sleep 1; perf script", and check for unknown frames there πŸ”

The most common reason for "[unknown]" frames is that the target software wasn't compiled with frame pointers, so we can't use that simple method for walking the stack. The fix is to use software that does have frame pointers, like gcc -fno-omit-frame-pointer, or Java's -XX:+PreserveFramePointer 🫢

Another reason is JIT compilers, which don't use a traditional symbol table. The fix there is to populate a /tmp/perf-PID.map file with the symbols, which this tool should read. How you do this depends on the runtime (Java, Node.js) 🧩

If you seem to have unrelated samples in the output, check for other sampling or tracing tools that may be running. The current version of this tool can include their events if profiling happened at the same time. Those samples may be filtered in a future version πŸ™ƒ


πŸ¦‹ OVERHEAD πŸ¦‹

This is an efficient profiler, as stack traces are frequency counted in kernel context, and only the unique stacks and their counts get passed to user space. Compare that with the current "perf record -F 99 -a" method, which writes each sample to user space (via a ring buffer) and then to the file system (perf.data), which then has to be post-processed. Messy 😩

This uses perf_event_open to set up a timer that's instrumented by BPF. For efficiency it does not initialize the perf ring buffer, so the redundant perf samples are never collected ✨

It's expected that the overhead while sampling at 49 Hertz (the default), across all CPUs, should be negligible. If you crank up the sample rate, the overhead might start to be measurable πŸ“ˆ


🌸 SOURCE 🌸

This comes from bcc πŸ’–

https://github.com/iovisor/bcc

Also look in the bcc distribution for a companion _examples.txt file with example usage, output, and commentary for this tool πŸ“š


🌈 OS 🌈

Linux 🐧


πŸ§ͺ STABILITY πŸ§ͺ

Unstable, since it's still in development 🚧


πŸ‘‘ AUTHOR πŸ‘‘

Brendan Gregg, the legend himself 🫑


πŸ¦‹ SEE ALSO πŸ¦‹

offcputime(8) πŸ’œ


USER COMMANDS, dated 2020-03-18, all from profile(8) πŸ’…βœ¨ bye bestie, stay curious 🫢🌈

πŸ“¦ where this page comes from