Commit 8996719b authored by Akilesh Kailash's avatar Akilesh Kailash Committed by yonghong-song

Add -d (duration) option to argdist, funclatency and syscount (#1768)

* Add -d (duration) option to argdist, funclatency and syscount

* Add -d option to man pages and _example.txt
parent 9733011a
......@@ -2,7 +2,7 @@
.SH NAME
argdist \- Trace a function and display a histogram or frequency count of its parameter values. Uses Linux eBPF/bcc.
.SH SYNOPSIS
.B argdist [-h] [-p PID] [-z STRING_SIZE] [-i INTERVAL] [-n COUNT] [-v] [-T TOP] [-H specifier] [-C specifier] [-I header]
.B argdist [-h] [-p PID] [-z STRING_SIZE] [-i INTERVAL] [-d DURATION] [-n COUNT] [-v] [-T TOP] [-H specifier] [-C specifier] [-I header]
.SH DESCRIPTION
argdist attaches to function entry and exit points, collects specified parameter
values, and stores them in a histogram or a frequency collection that counts
......@@ -27,6 +27,9 @@ characters. Longer strings will be truncated.
\-i INTERVAL
Print the collected data every INTERVAL seconds. The default is 1 second.
.TP
\-d DURATION
Total duration of trace in seconds.
.TP
\-n NUMBER
Print the collected data COUNT times and then exit.
.TP
......
......@@ -2,7 +2,7 @@
.SH NAME
funclatency \- Time functions and print latency as a histogram.
.SH SYNOPSIS
.B funclatency [\-h] [\-p PID] [\-i INTERVAL] [\-T] [\-u] [\-m] [\-F] [\-r] [\-v] pattern
.B funclatency [\-h] [\-p PID] [\-i INTERVAL] [\-d DURATION] [\-T] [\-u] [\-m] [\-F] [\-r] [\-v] pattern
.SH DESCRIPTION
This tool traces function calls and times their duration (latency), and
shows the latency distribution as a histogram. The time is measured from when
......@@ -37,6 +37,9 @@ Trace this process ID only.
\-i INTERVAL
Print output every interval seconds.
.TP
\-d DURATION
Total duration of trace, in seconds.
.TP
\-T
Include timestamps on output.
.TP
......@@ -72,6 +75,10 @@ Time do_nanosleep(), and print the histogram in units of milliseconds:
#
.B funclatency \-m do_nanosleep
.TP
Time libc open(), and print output every 2 seconds, for duration 10 seconds:
#
.B funclatency \-i 2 -d 10 c:read
.TP
Time vfs_read(), and print output every 5 seconds, with timestamps:
#
.B funclatency \-mTi 5 vfs_read
......
......@@ -2,7 +2,7 @@
.SH NAME
syscount \- Summarize syscall counts and latencies.
.SH SYNOPSIS
.B syscount [-h] [-p PID] [-i INTERVAL] [-T TOP] [-x] [-e ERRNO] [-L] [-m] [-P] [-l]
.B syscount [-h] [-p PID] [-i INTERVAL] [-d DURATION] [-T TOP] [-x] [-e ERRNO] [-L] [-m] [-P] [-l]
.SH DESCRIPTION
This tool traces syscall entry and exit tracepoints and summarizes either the
number of syscalls of each type, or the number of syscalls per process. It can
......@@ -23,6 +23,9 @@ Trace only this process.
\-i INTERVAL
Print the summary at the specified interval (in seconds).
.TP
\-d DURATION
Total duration of trace (in seconds).
.TP
\-T TOP
Print only this many entries. Default: 10.
.TP
......
......@@ -610,7 +610,9 @@ argdist -I 'kernel/sched/sched.h' \\
type=int,
help="maximum string size to read from char* arguments")
parser.add_argument("-i", "--interval", default=1, type=int,
help="output interval, in seconds")
help="output interval, in seconds (default 1 second)")
parser.add_argument("-d", "--duration", type=int,
help="total duration of trace, in seconds")
parser.add_argument("-n", "--number", type=int, dest="count",
help="number of outputs")
parser.add_argument("-v", "--verbose", action="store_true",
......@@ -684,9 +686,11 @@ struct __string_t { char s[%d]; };
def _main_loop(self):
count_so_far = 0
seconds = 0
while True:
try:
sleep(self.args.interval)
seconds += self.args.interval
except KeyboardInterrupt:
exit()
print("[%s]" % strftime("%H:%M:%S"))
......@@ -696,6 +700,9 @@ struct __string_t { char s[%d]; };
if self.args.count is not None and \
count_so_far >= self.args.count:
exit()
if self.args.duration and \
seconds >= self.args.duration:
exit()
def run(self):
try:
......
......@@ -348,7 +348,9 @@ optional arguments:
-z STRING_SIZE, --string-size STRING_SIZE
maximum string size to read from char* arguments
-i INTERVAL, --interval INTERVAL
output interval, in seconds
output interval, in seconds (default 1 second)
-d DURATION, --duration DURATION
total duration of trace, in seconds
-n COUNT, --number COUNT
number of outputs
-v, --verbose print resulting BPF program code before executing
......
......@@ -35,6 +35,7 @@ examples = """examples:
./funclatency c:read # time the read() C library function
./funclatency -u vfs_read # time vfs_read(), in microseconds
./funclatency -m do_nanosleep # time do_nanosleep(), in milliseconds
./funclatency -i 2 -d 10 c:open # output every 2 seconds, for duration 10s
./funclatency -mTi 5 vfs_read # output every 5 seconds, with timestamps
./funclatency -p 181 vfs_read # time process 181 only
./funclatency 'vfs_fstat*' # time both vfs_fstat() and vfs_fstatat()
......@@ -47,8 +48,10 @@ parser = argparse.ArgumentParser(
epilog=examples)
parser.add_argument("-p", "--pid", type=int,
help="trace this PID only")
parser.add_argument("-i", "--interval", default=99999999,
help="summary interval, seconds")
parser.add_argument("-i", "--interval", type=int,
help="summary interval, in seconds")
parser.add_argument("-d", "--duration", type=int,
help="total duration of trace, in seconds")
parser.add_argument("-T", "--timestamp", action="store_true",
help="include timestamp on output")
parser.add_argument("-u", "--microseconds", action="store_true",
......@@ -66,6 +69,10 @@ parser.add_argument("pattern",
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
if args.duration and not args.interval:
args.interval = args.duration
if not args.interval:
args.interval = 99999999
def bail(error):
print("Error: " + error)
......@@ -226,14 +233,18 @@ def print_section(key):
return "%s [%d]" % (BPF.sym(key[0], key[1]), key[1])
exiting = 0 if args.interval else 1
seconds = 0
dist = b.get_table("dist")
while (1):
try:
sleep(int(args.interval))
sleep(args.interval)
seconds += args.interval
except KeyboardInterrupt:
exiting = 1
# as cleanup can take many seconds, trap Ctrl-C:
signal.signal(signal.SIGINT, signal_ignore)
if args.duration and seconds >= args.duration:
exiting = 1
print()
if args.timestamp:
......
......@@ -343,7 +343,9 @@ optional arguments:
-h, --help show this help message and exit
-p PID, --pid PID trace this PID only
-i INTERVAL, --interval INTERVAL
summary interval, seconds
summary interval, in seconds
-d DURATION, --duration DURATION
total duration of trace, in seconds
-T, --timestamp include timestamp on output
-u, --microseconds microsecond histogram
-m, --milliseconds millisecond histogram
......@@ -357,6 +359,7 @@ examples:
./funclatency c:read # time the read() C library function
./funclatency -u vfs_read # time vfs_read(), in microseconds
./funclatency -m do_nanosleep # time do_nanosleep(), in milliseconds
./funclatency -i 2 -d 10 c:open # output every 2 seconds, for duration 10s
./funclatency -mTi 5 vfs_read # output every 5 seconds, with timestamps
./funclatency -p 181 vfs_read # time process 181 only
./funclatency 'vfs_fstat*' # time both vfs_fstat() and vfs_fstatat()
......
......@@ -17,6 +17,7 @@ import errno
import itertools
import subprocess
import sys
import signal
import platform
if sys.version_info.major < 3:
......@@ -370,6 +371,9 @@ except Exception as e:
else:
raise Exception("ausyscall: command not found")
# signal handler
def signal_ignore(signal, frame):
print()
def handle_errno(errstr):
try:
......@@ -388,6 +392,8 @@ parser = argparse.ArgumentParser(
parser.add_argument("-p", "--pid", type=int, help="trace only this pid")
parser.add_argument("-i", "--interval", type=int,
help="print summary at this interval (seconds)")
parser.add_argument("-d", "--duration", type=int,
help="total duration of trace, in seconds")
parser.add_argument("-T", "--top", type=int, default=10,
help="print only the top syscalls by count or latency")
parser.add_argument("-x", "--failures", action="store_true",
......@@ -405,6 +411,10 @@ parser.add_argument("-l", "--list", action="store_true",
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
if args.duration and not args.interval:
args.interval = args.duration
if not args.interval:
args.interval = 99999999
if args.list:
for grp in izip_longest(*(iter(sorted(syscalls.values())),) * 4):
......@@ -545,11 +555,20 @@ def print_latency_stats():
print("Tracing %ssyscalls, printing top %d... Ctrl+C to quit." %
("failed " if args.failures else "", args.top))
exiting = 0 if args.interval else 1
seconds = 0
while True:
try:
sleep(args.interval or 999999999)
print_stats()
sleep(args.interval)
seconds += args.interval
except KeyboardInterrupt:
if not args.interval:
exiting = 1
signal.signal(signal.SIGINT, signal_ignore)
if args.duration and seconds >= args.duration:
exiting = 1
print_stats()
break
if exiting:
print("Detaching...")
exit()
......@@ -151,6 +151,8 @@ optional arguments:
-p PID, --pid PID trace only this pid
-i INTERVAL, --interval INTERVAL
print summary at this interval (seconds)
-d DURATION, --duration DURATION
total duration of trace, in seconds
-T TOP, --top TOP print only the top syscalls by count or latency
-x, --failures trace only failed syscalls (return < 0)
-e ERRNO, --errno ERRNO
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment