Skip to content

Commit

Permalink
tools/cpudist: Exclude CPU idle time by default
Browse files Browse the repository at this point in the history
  • Loading branch information
xingfeng2510 authored and yonghong-song committed Mar 28, 2022
1 parent e683daa commit c1a767b
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 7 deletions.
11 changes: 10 additions & 1 deletion man/man8/cpudist.8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.SH NAME
cpudist \- On- and off-CPU task time as a histogram.
.SH SYNOPSIS
.B cpudist [\-h] [-O] [\-T] [\-m] [\-P] [\-L] [\-p PID] [interval] [count]
.B cpudist [\-h] [-O] [\-T] [\-m] [\-P] [\-L] [\-p PID] [\-I] [interval] [count]
.SH DESCRIPTION
This measures the time a task spends on the CPU before being descheduled, and
shows the times as a histogram. Tasks that spend a very short time on the CPU
Expand All @@ -15,6 +15,8 @@ is scheduled again. This can be helpful in identifying long blocking and I/O
operations, or alternatively very short descheduling times due to short-lived
locks or timers.

By default CPU idle time are excluded by simply excluding PID 0.

This tool uses in-kernel eBPF maps for storing timestamps and the histogram,
for efficiency. Despite this, the overhead of this tool may become significant
for some workloads: see the OVERHEAD section.
Expand Down Expand Up @@ -45,6 +47,9 @@ Print a histogram for each TID (pid from the kernel's perspective).
\-p PID
Only show this PID (filtered in kernel for efficiency).
.TP
\-I
Include CPU idle time (by default these are excluded).
.TP
interval
Output interval, in seconds.
.TP
Expand All @@ -71,6 +76,10 @@ Print 1 second summaries, using milliseconds as units for the histogram, and inc
Trace PID 185 only, 1 second summaries:
#
.B cpudist -p 185 1
.TP
Include CPU idle time:
#
.B cpudist -I
.SH FIELDS
.TP
usecs
Expand Down
30 changes: 25 additions & 5 deletions tools/cpudist.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
#
# cpudist Summarize on- and off-CPU time per task as a histogram.
#
# USAGE: cpudist [-h] [-O] [-T] [-m] [-P] [-L] [-p PID] [interval] [count]
# USAGE: cpudist [-h] [-O] [-T] [-m] [-P] [-L] [-p PID] [-I] [interval] [count]
#
# This measures the time a task spends on or off the CPU, and shows this time
# as a histogram, optionally per-process.
#
# By default CPU idle time are excluded by simply excluding PID 0.
#
# Copyright 2016 Sasha Goldshtein
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 27-Mar-2022 Rocky Xing Changed to exclude CPU idle time by default.

from __future__ import print_function
from bcc import BPF
Expand All @@ -23,6 +27,7 @@
cpudist -mT 1 # 1s summaries, milliseconds, and timestamps
cpudist -P # show each PID separately
cpudist -p 185 # trace PID 185 only
cpudist -I # include CPU idle time
"""
parser = argparse.ArgumentParser(
description="Summarize on-CPU time per task as a histogram.",
Expand All @@ -40,6 +45,8 @@
help="print a histogram per thread ID")
parser.add_argument("-p", "--pid",
help="trace this PID only")
parser.add_argument("-I", "--include-idle", action="store_true",
help="include CPU idle time")
parser.add_argument("interval", nargs="?", default=99999999,
help="output interval, in seconds")
parser.add_argument("count", nargs="?", default=99999999,
Expand Down Expand Up @@ -74,7 +81,10 @@
static inline void store_start(u32 tgid, u32 pid, u32 cpu, u64 ts)
{
if (FILTER)
if (PID_FILTER)
return;
if (IDLE_FILTER)
return;
entry_key_t entry_key = { .pid = pid, .cpu = cpu };
Expand All @@ -83,7 +93,10 @@
static inline void update_hist(u32 tgid, u32 pid, u32 cpu, u64 ts)
{
if (FILTER)
if (PID_FILTER)
return;
if (IDLE_FILTER)
return;
entry_key_t entry_key = { .pid = pid, .cpu = cpu };
Expand Down Expand Up @@ -128,9 +141,16 @@
"""

if args.pid:
bpf_text = bpf_text.replace('FILTER', 'tgid != %s' % args.pid)
bpf_text = bpf_text.replace('PID_FILTER', 'tgid != %s' % args.pid)
else:
bpf_text = bpf_text.replace('FILTER', '0')
bpf_text = bpf_text.replace('PID_FILTER', '0')

# set idle filter
idle_filter = 'pid == 0'
if args.include_idle:
idle_filter = '0'
bpf_text = bpf_text.replace('IDLE_FILTER', idle_filter)

if args.milliseconds:
bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000000;')
label = "msecs"
Expand Down
7 changes: 6 additions & 1 deletion tools/cpudist_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ that can indicate oversubscription (too many tasks for too few processors),
overhead due to excessive context switching (e.g. a common shared lock for
multiple threads), uneven workload distribution, too-granular tasks, and more.

By default CPU idle time are excluded by simply excluding PID 0.

Alternatively, the same options are available for summarizing task off-CPU
time, which helps understand how often threads are being descheduled and how
long they spend waiting for I/O, locks, timers, and other causes of suspension.
Expand Down Expand Up @@ -280,7 +282,7 @@ USAGE message:

# ./cpudist.py -h

usage: cpudist.py [-h] [-O] [-T] [-m] [-P] [-L] [-p PID] [interval] [count]
usage: cpudist.py [-h] [-O] [-T] [-m] [-P] [-L] [-p PID] [-I] [interval] [count]

Summarize on-CPU time per task as a histogram.

Expand All @@ -296,6 +298,7 @@ optional arguments:
-P, --pids print a histogram per process ID
-L, --tids print a histogram per thread ID
-p PID, --pid PID trace this PID only
-I, --include-idle include CPU idle time

examples:
cpudist # summarize on-CPU time as a histogram
Expand All @@ -304,3 +307,5 @@ examples:
cpudist -mT 1 # 1s summaries, milliseconds, and timestamps
cpudist -P # show each PID separately
cpudist -p 185 # trace PID 185 only
cpudist -I # include CPU idle time

0 comments on commit c1a767b

Please sign in to comment.