diff options
author | Marko Myllynen <myllynen@redhat.com> | 2018-09-26 20:09:07 +0300 |
---|---|---|
committer | yonghong-song <ys114321@gmail.com> | 2018-09-26 10:09:07 -0700 |
commit | 27e7aeab5d7b9f0f4259fb0f996274af0521243f (patch) | |
tree | 0ae870d5b088e56bdee091627a043957a4de6f8d | |
parent | 3d2211632247ad0d1ee9d1ecc1162764322eb974 (diff) | |
download | bcc-27e7aeab5d7b9f0f4259fb0f996274af0521243f.zip bcc-27e7aeab5d7b9f0f4259fb0f996274af0521243f.tar.gz bcc-27e7aeab5d7b9f0f4259fb0f996274af0521243f.tar.bz2 |
tools: continue adding --ebpf support (#1986)
Use argparse in cachestat, add --ebpf support.
Add --ebpf support for u* tools, finalize language sorting.
Remove sole --ebpf string on usage line in tcpsubnet.
-rwxr-xr-x | tools/cachestat.py | 64 | ||||
-rwxr-xr-x | tools/lib/ucalls.py | 8 | ||||
-rwxr-xr-x | tools/lib/uflow.py | 9 | ||||
-rwxr-xr-x | tools/lib/ugc.py | 43 | ||||
-rwxr-xr-x | tools/lib/uobjnew.py | 45 | ||||
-rwxr-xr-x | tools/lib/ustat.py | 6 | ||||
-rwxr-xr-x | tools/lib/uthreads.py | 9 | ||||
-rwxr-xr-x | tools/tcpsubnet.py | 2 |
8 files changed, 102 insertions, 84 deletions
diff --git a/tools/cachestat.py b/tools/cachestat.py index 573c697..b00c804 100755 --- a/tools/cachestat.py +++ b/tools/cachestat.py @@ -19,6 +19,7 @@ from __future__ import print_function from bcc import BPF from time import sleep, strftime +import argparse import signal import re from sys import argv @@ -48,43 +49,25 @@ misses = 0 hits = 0 debug = 0 -# args -def usage(): - print("USAGE: %s [-T] [ interval [count] ]" % argv[0]) - exit() - # arguments -interval = 5 -count = -1 -tstamp = 0 - -if len(argv) > 1: - if str(argv[1]) == '-T': - tstamp = 1 - -if len(argv) > 1 and tstamp == 0: - try: - if int(argv[1]) > 0: - interval = int(argv[1]) - if len(argv) > 2: - if int(argv[2]) > 0: - count = int(argv[2]) - except: - usage() - -elif len(argv) > 2 and tstamp == 1: - try: - if int(argv[2]) > 0: - interval = int(argv[2]) - if len(argv) >= 4: - if int(argv[3]) > 0: - count = int(argv[3]) - except: - usage() - -# load BPF program +parser = argparse.ArgumentParser( + description="Count cache kernel function calls", + formatter_class=argparse.RawDescriptionHelpFormatter) +parser.add_argument("-T", "--timestamp", action="store_true", + help="include timestamp on output") +parser.add_argument("interval", nargs="?", default=5, + help="output interval, in seconds") +parser.add_argument("count", nargs="?", default=-1, + help="number of outputs") +parser.add_argument("--ebpf", action="store_true", + help=argparse.SUPPRESS) +args = parser.parse_args() +count = int(args.count) +tstamp = args.timestamp +interval = int(args.interval) + +# define BPF program bpf_text = """ - #include <uapi/linux/ptrace.h> struct key_t { u64 ip; @@ -102,6 +85,13 @@ int do_count(struct pt_regs *ctx) { } """ + +if debug or args.ebpf: + print(bpf_text) + if args.ebpf: + exit() + +# load BPF program b = BPF(text=bpf_text) b.attach_kprobe(event="add_to_page_cache_lru", fn_name="do_count") b.attach_kprobe(event="mark_page_accessed", fn_name="do_count") @@ -129,7 +119,7 @@ while 1: # as cleanup can take many seconds, trap Ctrl-C: signal.signal(signal.SIGINT, signal_ignore) - counts = b.get_table("counts") + counts = b["counts"] for k, v in sorted(counts.items(), key=lambda counts: counts[1].value): if re.match(b'mark_page_accessed', b.ksym(k.ip)) is not None: @@ -175,7 +165,7 @@ while 1: cached = int(mem["Cached"]) / 1024 buff = int(mem["Buffers"]) / 1024 - if tstamp == 1: + if tstamp: print("%-8s " % strftime("%H:%M:%S"), end="") print("%8d %8d %8d %8d %12.0f %10.0f" % (total, misses, hits, mbd, buff, cached)) diff --git a/tools/lib/ucalls.py b/tools/lib/ucalls.py index b2d165c..1a0fe21 100755 --- a/tools/lib/ucalls.py +++ b/tools/lib/ucalls.py @@ -49,6 +49,8 @@ parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode: print the BPF program (for debugging purposes)") parser.add_argument("-m", "--milliseconds", action="store_true", help="report times in milliseconds (default is microseconds)") +parser.add_argument("--ebpf", action="store_true", + help=argparse.SUPPRESS) args = parser.parse_args() language = args.language @@ -243,10 +245,12 @@ if language: else: usdt = None -if args.verbose: - if usdt: +if args.ebpf or args.verbose: + if args.verbose and usdt: print(usdt.get_text()) print(program) + if args.ebpf: + exit() bpf = BPF(text=program, usdt_contexts=[usdt] if usdt else []) if args.syscalls: diff --git a/tools/lib/uflow.py b/tools/lib/uflow.py index 8419c88..fb306e3 100755 --- a/tools/lib/uflow.py +++ b/tools/lib/uflow.py @@ -39,6 +39,8 @@ parser.add_argument("-C", "--class", dest="clazz", help="trace only calls to classes starting with this prefix") parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode: print the BPF program (for debugging purposes)") +parser.add_argument("--ebpf", action="store_true", + help=argparse.SUPPRESS) args = parser.parse_args() usdt = USDT(pid=args.pid) @@ -165,9 +167,12 @@ else: print("No language detected; use -l to trace a language.") exit(1) -if args.verbose: - print(usdt.get_text()) +if args.ebpf or args.verbose: + if args.verbose: + print(usdt.get_text()) print(program) + if args.ebpf: + exit() bpf = BPF(text=program, usdt_contexts=[usdt]) print("Tracing method calls in %s process %d... Ctrl-C to quit." % diff --git a/tools/lib/ugc.py b/tools/lib/ugc.py index 9f4d258..8288910 100755 --- a/tools/lib/ugc.py +++ b/tools/lib/ugc.py @@ -4,7 +4,7 @@ # ugc Summarize garbage collection events in high-level languages. # For Linux, uses BCC, eBPF. # -# USAGE: ugc [-v] [-m] [-M MSEC] [-F FILTER] {java,python,ruby,node} pid +# USAGE: ugc [-v] [-m] [-M MSEC] [-F FILTER] {java,node,python,ruby} pid # # Copyright 2016 Sasha Goldshtein # Licensed under the Apache License, Version 2.0 (the "License") @@ -18,7 +18,7 @@ import ctypes as ct import time import os -languages = ["java", "python", "ruby", "node"] +languages = ["java", "node", "python", "ruby"] examples = """examples: ./ugc -l java 185 # trace Java GCs in process 185 @@ -40,6 +40,8 @@ parser.add_argument("-M", "--minimum", type=int, default=0, help="display only GCs longer than this many milliseconds") parser.add_argument("-F", "--filter", type=str, help="display only GCs whose description contains this text") +parser.add_argument("--ebpf", action="store_true", + help=argparse.SUPPRESS) args = parser.parse_args() usdt = USDT(pid=args.pid) @@ -150,6 +152,21 @@ if language == "java": probes.append(Probe("gc__begin", "gc__end", "", "", lambda _: "no additional info available")) # +# Node +# +elif language == "node": + end_save = """ + u32 gc_type = 0; + bpf_usdt_readarg(1, ctx, &gc_type); + event.field1 = gc_type; + """ + descs = {"GC scavenge": 1, "GC mark-sweep-compact": 2, + "GC incremental mark": 4, "GC weak callbacks": 8} + probes.append(Probe("gc__start", "gc__done", "", end_save, + lambda e: str.join(", ", + [desc for desc, val in descs.items() + if e.field1 & val != 0]))) +# # Python # elif language == "python": @@ -179,21 +196,6 @@ elif language == "ruby": "", "", lambda _: "GC mark stage")) probes.append(Probe("gc__sweep__begin", "gc__sweep__end", "", "", lambda _: "GC sweep stage")) -# -# Node -# -elif language == "node": - end_save = """ - u32 gc_type = 0; - bpf_usdt_readarg(1, ctx, &gc_type); - event.field1 = gc_type; - """ - descs = {"GC scavenge": 1, "GC mark-sweep-compact": 2, - "GC incremental mark": 4, "GC weak callbacks": 8} - probes.append(Probe("gc__start", "gc__done", "", end_save, - lambda e: str.join(", ", - [desc for desc, val in descs.items() - if e.field1 & val != 0]))) else: print("No language detected; use -l to trace a language.") @@ -204,9 +206,12 @@ for probe in probes: program += probe.generate() probe.attach() -if args.verbose: - print(usdt.get_text()) +if args.ebpf or args.verbose: + if args.verbose: + print(usdt.get_text()) print(program) + if args.ebpf: + exit() bpf = BPF(text=program, usdt_contexts=[usdt]) print("Tracing garbage collections in %s process %d... Ctrl-C to quit." % diff --git a/tools/lib/uobjnew.py b/tools/lib/uobjnew.py index bcd69b4..e3b61ff 100755 --- a/tools/lib/uobjnew.py +++ b/tools/lib/uobjnew.py @@ -4,7 +4,7 @@ # uobjnew Summarize object allocations in high-level languages. # For Linux, uses BCC, eBPF. # -# USAGE: uobjnew [-h] [-T TOP] [-v] {java,ruby,c} pid [interval] +# USAGE: uobjnew [-h] [-T TOP] [-v] {c,java,ruby} pid [interval] # # Copyright 2016 Sasha Goldshtein # Licensed under the Apache License, Version 2.0 (the "License") @@ -18,7 +18,7 @@ from time import sleep import os # C needs to be the last language. -languages = ["java", "ruby", "c"] +languages = ["c", "java", "ruby"] examples = """examples: ./uobjnew -l java 145 # summarize Java allocations in process 145 @@ -41,6 +41,8 @@ parser.add_argument("-S", "--top-size", type=int, help="number of largest types by allocated bytes to print") parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode: print the BPF program (for debugging purposes)") +parser.add_argument("--ebpf", action="store_true", + help=argparse.SUPPRESS) args = parser.parse_args() language = args.language @@ -69,9 +71,24 @@ BPF_HASH(allocs, struct key_t, struct val_t); usdt = USDT(pid=args.pid) # +# C +# +if language == "c": + program += """ +int alloc_entry(struct pt_regs *ctx, size_t size) { + struct key_t key = {}; + struct val_t *valp, zero = {}; + key.size = size; + valp = allocs.lookup_or_init(&key, &zero); + valp->total_size += size; + valp->num_allocs += 1; + return 0; +} + """ +# # Java # -if language == "java": +elif language == "java": program += """ int alloc_entry(struct pt_regs *ctx) { struct key_t key = {}; @@ -120,30 +137,18 @@ int object_alloc_entry(struct pt_regs *ctx) { program += create_template.replace("THETHING", thing) usdt.enable_probe_or_bail("%s__create" % thing, "%s_alloc_entry" % thing) -# -# C -# -elif language == "c": - program += """ -int alloc_entry(struct pt_regs *ctx, size_t size) { - struct key_t key = {}; - struct val_t *valp, zero = {}; - key.size = size; - valp = allocs.lookup_or_init(&key, &zero); - valp->total_size += size; - valp->num_allocs += 1; - return 0; -} - """ else: print("No language detected; use -l to trace a language.") exit(1) -if args.verbose: - print(usdt.get_text()) +if args.ebpf or args.verbose: + if args.verbose: + print(usdt.get_text()) print(program) + if args.ebpf: + exit() bpf = BPF(text=program, usdt_contexts=[usdt]) if language == "c": diff --git a/tools/lib/ustat.py b/tools/lib/ustat.py index 8b2f80f..7ac0967 100755 --- a/tools/lib/ustat.py +++ b/tools/lib/ustat.py @@ -147,6 +147,8 @@ class Tool(object): help="output interval, in seconds") parser.add_argument("count", nargs="?", default=99999999, type=int, help="number of outputs") + parser.add_argument("--ebpf", action="store_true", + help=argparse.SUPPRESS) self.args = parser.parse_args() def _create_probes(self): @@ -197,8 +199,10 @@ class Tool(object): def _attach_probes(self): program = str.join('\n', [p.get_program() for p in self.probes]) - if self.args.debug: + if self.args.debug or self.args.ebpf: print(program) + if self.args.ebpf: + exit() for probe in self.probes: print("Attached to %s processes:" % probe.language, str.join(', ', map(str, probe.targets))) diff --git a/tools/lib/uthreads.py b/tools/lib/uthreads.py index a96750f..fb54599 100755 --- a/tools/lib/uthreads.py +++ b/tools/lib/uthreads.py @@ -34,6 +34,8 @@ parser.add_argument("-l", "--language", choices=languages + ["none"], parser.add_argument("pid", type=int, help="process id to attach to") parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode: print the BPF program (for debugging purposes)") +parser.add_argument("--ebpf", action="store_true", + help=argparse.SUPPRESS) args = parser.parse_args() usdt = USDT(pid=args.pid) @@ -88,9 +90,12 @@ int %s(struct pt_regs *ctx) { usdt.enable_probe_or_bail("thread__start", "trace_start") usdt.enable_probe_or_bail("thread__stop", "trace_stop") -if args.verbose: - print(usdt.get_text()) +if args.ebpf or args.verbose: + if args.verbose: + print(usdt.get_text()) print(program) + if args.ebpf: + exit() bpf = BPF(text=program, usdt_contexts=[usdt]) print("Tracing thread events in process %d (language: %s)... Ctrl-C to quit." % diff --git a/tools/tcpsubnet.py b/tools/tcpsubnet.py index 328f426..5f2a806 100755 --- a/tools/tcpsubnet.py +++ b/tools/tcpsubnet.py @@ -4,7 +4,7 @@ # tcpsubnet Summarize TCP bytes sent to different subnets. # For Linux, uses BCC, eBPF. Embedded C. # -# USAGE: tcpsubnet [-h] [-v] [--ebpf] [-J] [-f FORMAT] [-i INTERVAL] [subnets] +# USAGE: tcpsubnet [-h] [-v] [-J] [-f FORMAT] [-i INTERVAL] [subnets] # # This uses dynamic tracing of kernel functions, and will need to be updated # to match kernel changes. |