From d2f4762a615d93cc54fa11c3917a2b33f4049717 Mon Sep 17 00:00:00 2001 From: Sasha Goldshtein Date: Tue, 4 Oct 2016 18:40:15 +0300 Subject: [PATCH] argdist: Cumulative mode (-c) (#719) By default, argdist now clears the histograms or freq count maps after each display interval. The new `-c` option enables cumulative mode, where maps are not cleared at each interval. This fixes #718. --- tools/argdist.py | 13 +++++++++---- tools/argdist_example.txt | 17 +++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/tools/argdist.py b/tools/argdist.py index 12edded..b49d549 100755 --- a/tools/argdist.py +++ b/tools/argdist.py @@ -4,7 +4,7 @@ # parameter values as a histogram or frequency count. # # USAGE: argdist [-h] [-p PID] [-z STRING_SIZE] [-i INTERVAL] -# [-n COUNT] [-v] [-T TOP] +# [-n COUNT] [-v] [-c] [-T TOP] # [-C specifier [specifier ...]] # [-H specifier [specifier ...]] # [-I header [header ...]] @@ -178,6 +178,7 @@ u64 __time = bpf_ktime_get_ns(); def __init__(self, tool, type, specifier): self.usdt_ctx = None self.pid = tool.args.pid + self.cumulative = tool.args.cumulative or False self.raw_spec = specifier self._validate_specifier() @@ -451,10 +452,10 @@ int PROBENAME(struct pt_regs *ctx SIGNATURE) if self.type == "freq": print(self.label or self.raw_spec) print("\t%-10s %s" % ("COUNT", "EVENT")) - data = sorted(data.items(), key=lambda kv: kv[1].value) + sdata = sorted(data.items(), key=lambda kv: kv[1].value) if top is not None: - data = data[-top:] - for key, value in data: + sdata = sdata[-top:] + for key, value in sdata: # Print some nice values if the user didn't # specify an expression to probe if self.is_default_expr: @@ -471,6 +472,8 @@ int PROBENAME(struct pt_regs *ctx SIGNATURE) label = self.label or (self._display_expr(0) if not self.is_default_expr else "retval") data.print_log2_hist(val_type=label) + if not self.cumulative: + data.clear() def __str__(self): return self.label or self.raw_spec @@ -571,6 +574,8 @@ argdist -p 2780 -z 120 \\ help="number of outputs") parser.add_argument("-v", "--verbose", action="store_true", help="print resulting BPF program code before executing") + parser.add_argument("-c", "--cumulative", action="store_true", + help="do not clear histograms and freq counts at each interval") parser.add_argument("-T", "--top", type=int, help="number of top results to show (not applicable to " + "histograms)") diff --git a/tools/argdist_example.txt b/tools/argdist_example.txt index d851337..789bd3a 100644 --- a/tools/argdist_example.txt +++ b/tools/argdist_example.txt @@ -10,7 +10,7 @@ various functions. For example, suppose you want to find what allocation sizes are common in your application: -# ./argdist -p 2420 -C 'p:c:malloc(size_t size):size_t:size' +# ./argdist -p 2420 -c -C 'p:c:malloc(size_t size):size_t:size' [01:42:29] p:c:malloc(size_t size):size_t:size COUNT EVENT @@ -43,7 +43,7 @@ probed and its value was 16, repeatedly. Now, suppose you wanted a histogram of buffer sizes passed to the write() function across the system: -# ./argdist -H 'p:c:write(int fd, void *buf, size_t len):size_t:len' +# ./argdist -c -H 'p:c:write(int fd, void *buf, size_t len):size_t:len' [01:45:22] p:c:write(int fd, void *buf, size_t len):size_t:len len : count distribution @@ -81,7 +81,7 @@ bytes, medium writes of 32-63 bytes, and larger writes of 64-127 bytes. But these are writes across the board -- what if you wanted to focus on writes to STDOUT? -# ./argdist -H 'p:c:write(int fd, void *buf, size_t len):size_t:len:fd==1' +# ./argdist -c -H 'p:c:write(int fd, void *buf, size_t len):size_t:len:fd==1' [01:47:17] p:c:write(int fd, void *buf, size_t len):size_t:len:fd==1 len : count distribution @@ -232,7 +232,7 @@ multiple microseconds per byte. You could also group results by more than one field. For example, __kmalloc takes an additional flags parameter that describes how to allocate memory: -# ./argdist -C 'p::__kmalloc(size_t size, gfp_t flags):gfp_t,size_t:flags,size' +# ./argdist -c -C 'p::__kmalloc(size_t size, gfp_t flags):gfp_t,size_t:flags,size' [03:42:29] p::__kmalloc(size_t size, gfp_t flags):gfp_t,size_t:flags,size COUNT EVENT @@ -268,7 +268,7 @@ between kernel versions like function signatures tend to. For example, let's trace the net:net_dev_start_xmit tracepoint and print the interface name that is transmitting: -# argdist -C 't:net:net_dev_start_xmit(void *a, void *b, struct net_device *c):char*:c->name' -n 2 +# argdist -c -C 't:net:net_dev_start_xmit(void *a, void *b, struct net_device *c):char*:c->name' -n 2 [05:01:10] t:net:net_dev_start_xmit(void *a, void *b, struct net_device *c):char*:c->name COUNT EVENT @@ -286,7 +286,7 @@ tracepoint is defined in the include/trace/events/net.h header file. Here's a final example that finds how many write() system calls are performed by each process on the system: -# argdist -C 'p:c:write():int:$PID;write per process' -n 2 +# argdist -c -C 'p:c:write():int:$PID;write per process' -n 2 [06:47:18] write by process COUNT EVENT @@ -305,8 +305,8 @@ USAGE message: # argdist -h usage: argdist [-h] [-p PID] [-z STRING_SIZE] [-i INTERVAL] [-n COUNT] [-v] - [-T TOP] [-H [specifier [specifier ...]]] - [-C [specifier [specifier ...]]] [-I [header [header ...]]] + [-c] [-T TOP] [-H [specifier [specifier ...]]] + [-C [specifier [specifier ...]]] [-I [header [header ...]]] Trace a function and display a summary of its parameter values. @@ -320,6 +320,7 @@ optional arguments: -n COUNT, --number COUNT number of outputs -v, --verbose print resulting BPF program code before executing + -c, --cumulative do not clear histograms and freq counts at each interval -T TOP, --top TOP number of top results to show (not applicable to histograms) -H [specifier [specifier ...]], --histogram [specifier [specifier ...]] -- 2.7.4