xref: /aosp_15_r20/external/bcc/examples/usdt_sample/scripts/latency.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python
2*387f9dfdSAndroid Build Coastguard Workerimport argparse
3*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep
4*387f9dfdSAndroid Build Coastguard Workerfrom sys import argv
5*387f9dfdSAndroid Build Coastguard Workerimport ctypes as ct
6*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, USDT
7*387f9dfdSAndroid Build Coastguard Workerimport inspect
8*387f9dfdSAndroid Build Coastguard Workerimport os
9*387f9dfdSAndroid Build Coastguard Worker
10*387f9dfdSAndroid Build Coastguard Worker# Parse command line arguments
11*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(description="Trace the latency of an operation using usdt probes.",
12*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter)
13*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", type=int, help="The id of the process to trace.")
14*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-f", "--filterstr", type=str, default="", help="The prefix filter for the operation input. If specified, only operations for which the input string starts with the filterstr are traced.")
15*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output generated bpf program and verbose logging information.")
16*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-s", "--sdt", dest="sdt", action="store_true", help="If true, will use the probes, created by systemtap's dtrace.")
17*387f9dfdSAndroid Build Coastguard Worker
18*387f9dfdSAndroid Build Coastguard Workerparser.set_defaults(verbose=False)
19*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
20*387f9dfdSAndroid Build Coastguard Workerthis_pid = int(args.pid)
21*387f9dfdSAndroid Build Coastguard Workerthis_filter = str(args.filterstr)
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard WorkerdebugLevel=0
24*387f9dfdSAndroid Build Coastguard Workerif args.verbose:
25*387f9dfdSAndroid Build Coastguard Worker    debugLevel=4
26*387f9dfdSAndroid Build Coastguard Worker
27*387f9dfdSAndroid Build Coastguard Worker# BPF program
28*387f9dfdSAndroid Build Coastguard Workerbpf_text_shared = "%s/bpf_text_shared.c" % os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
29*387f9dfdSAndroid Build Coastguard Workerbpf_text = open(bpf_text_shared, 'r').read()
30*387f9dfdSAndroid Build Coastguard Workerbpf_text += """
31*387f9dfdSAndroid Build Coastguard Worker
32*387f9dfdSAndroid Build Coastguard Worker/**
33*387f9dfdSAndroid Build Coastguard Worker * @brief Contains the latency data w.r.t. the complete operation from request to response.
34*387f9dfdSAndroid Build Coastguard Worker */
35*387f9dfdSAndroid Build Coastguard Workerstruct end_data_t
36*387f9dfdSAndroid Build Coastguard Worker{
37*387f9dfdSAndroid Build Coastguard Worker    u64 operation_id; ///< The id of the operation.
38*387f9dfdSAndroid Build Coastguard Worker    char input[64];   ///< The request (input) string.
39*387f9dfdSAndroid Build Coastguard Worker    char output[64];  ///< The response (output) string.
40*387f9dfdSAndroid Build Coastguard Worker    u64 start;        ///< The start timestamp of the operation.
41*387f9dfdSAndroid Build Coastguard Worker    u64 end;          ///< The end timestamp of the operation.
42*387f9dfdSAndroid Build Coastguard Worker    u64 duration;     ///< The duration of the operation.
43*387f9dfdSAndroid Build Coastguard Worker};
44*387f9dfdSAndroid Build Coastguard Worker
45*387f9dfdSAndroid Build Coastguard Worker/**
46*387f9dfdSAndroid Build Coastguard Worker * The output buffer, which will be used to push the latency event data to user space.
47*387f9dfdSAndroid Build Coastguard Worker */
48*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(operation_event);
49*387f9dfdSAndroid Build Coastguard Worker
50*387f9dfdSAndroid Build Coastguard Worker/**
51*387f9dfdSAndroid Build Coastguard Worker * @brief Reads the operation response arguments, calculates the latency event data, and writes it to the user output buffer.
52*387f9dfdSAndroid Build Coastguard Worker * @param ctx The BPF context.
53*387f9dfdSAndroid Build Coastguard Worker */
54*387f9dfdSAndroid Build Coastguard Workerint trace_operation_end(struct pt_regs* ctx)
55*387f9dfdSAndroid Build Coastguard Worker{
56*387f9dfdSAndroid Build Coastguard Worker    u64 operation_id;
57*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg(1, ctx, &operation_id);
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker    struct start_data_t* start_data = start_hash.lookup(&operation_id);
60*387f9dfdSAndroid Build Coastguard Worker    if (0 == start_data) {
61*387f9dfdSAndroid Build Coastguard Worker        return 0;
62*387f9dfdSAndroid Build Coastguard Worker    }
63*387f9dfdSAndroid Build Coastguard Worker
64*387f9dfdSAndroid Build Coastguard Worker    struct end_data_t end_data = {};
65*387f9dfdSAndroid Build Coastguard Worker    end_data.operation_id = operation_id;
66*387f9dfdSAndroid Build Coastguard Worker    bpf_usdt_readarg_p(2, ctx, &end_data.output, sizeof(end_data.output));
67*387f9dfdSAndroid Build Coastguard Worker    end_data.end = bpf_ktime_get_ns();
68*387f9dfdSAndroid Build Coastguard Worker    end_data.start = start_data->start;
69*387f9dfdSAndroid Build Coastguard Worker    end_data.duration = end_data.end - end_data.start;
70*387f9dfdSAndroid Build Coastguard Worker    __builtin_memcpy(&end_data.input, start_data->input, sizeof(end_data.input));
71*387f9dfdSAndroid Build Coastguard Worker
72*387f9dfdSAndroid Build Coastguard Worker    start_hash.delete(&end_data.operation_id);
73*387f9dfdSAndroid Build Coastguard Worker
74*387f9dfdSAndroid Build Coastguard Worker    operation_event.perf_submit(ctx, &end_data, sizeof(end_data));
75*387f9dfdSAndroid Build Coastguard Worker    return 0;
76*387f9dfdSAndroid Build Coastguard Worker}
77*387f9dfdSAndroid Build Coastguard Worker"""
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace("FILTER_STRING", this_filter)
80*387f9dfdSAndroid Build Coastguard Workerif this_filter:
81*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace("FILTER_STATEMENT", "if (!filter(start_data.input)) { return 0; }")
82*387f9dfdSAndroid Build Coastguard Workerelse:
83*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace("FILTER_STATEMENT", "")
84*387f9dfdSAndroid Build Coastguard Worker
85*387f9dfdSAndroid Build Coastguard Worker# Create USDT context
86*387f9dfdSAndroid Build Coastguard Workerprint("latency.py - Attaching probes to pid: %d; filter: %s" % (this_pid, this_filter))
87*387f9dfdSAndroid Build Coastguard Workerusdt_ctx = USDT(pid=this_pid)
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Workerif args.sdt:
90*387f9dfdSAndroid Build Coastguard Worker    usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_start_sdt", fn_name="trace_operation_start")
91*387f9dfdSAndroid Build Coastguard Worker    usdt_ctx.enable_probe(probe="usdt_sample_lib1_sdt:operation_end_sdt", fn_name="trace_operation_end")
92*387f9dfdSAndroid Build Coastguard Workerelse:
93*387f9dfdSAndroid Build Coastguard Worker    usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_start", fn_name="trace_operation_start")
94*387f9dfdSAndroid Build Coastguard Worker    usdt_ctx.enable_probe(probe="usdt_sample_lib1:operation_end", fn_name="trace_operation_end")
95*387f9dfdSAndroid Build Coastguard Worker
96*387f9dfdSAndroid Build Coastguard Worker# Create BPF context, load BPF program
97*387f9dfdSAndroid Build Coastguard Workerbpf_ctx = BPF(text=bpf_text, usdt_contexts=[usdt_ctx], debug=debugLevel)
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Worker# Define latency event and print function
100*387f9dfdSAndroid Build Coastguard Workerclass OperationEventData(ct.Structure):
101*387f9dfdSAndroid Build Coastguard Worker  _fields_ = [("operation_id", ct.c_ulonglong),
102*387f9dfdSAndroid Build Coastguard Worker              ("input", ct.c_char * 64),
103*387f9dfdSAndroid Build Coastguard Worker              ("output", ct.c_char * 64),
104*387f9dfdSAndroid Build Coastguard Worker              ("start", ct.c_ulonglong),
105*387f9dfdSAndroid Build Coastguard Worker              ("end", ct.c_ulonglong),
106*387f9dfdSAndroid Build Coastguard Worker              ("duration", ct.c_ulonglong)]
107*387f9dfdSAndroid Build Coastguard Worker
108*387f9dfdSAndroid Build Coastguard Workerstart = 0
109*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
110*387f9dfdSAndroid Build Coastguard Worker    global start
111*387f9dfdSAndroid Build Coastguard Worker    event = ct.cast(data, ct.POINTER(OperationEventData)).contents
112*387f9dfdSAndroid Build Coastguard Worker    if start == 0:
113*387f9dfdSAndroid Build Coastguard Worker        start = event.start
114*387f9dfdSAndroid Build Coastguard Worker    time_s = (float(event.start - start)) / 1000000000
115*387f9dfdSAndroid Build Coastguard Worker    latency = (float(event.duration) / 1000)
116*387f9dfdSAndroid Build Coastguard Worker    print("%-18.9f %-10d %-32s %-32s %16d %16d %16d" % (time_s, event.operation_id, event.input, event.output, event.start, event.end, latency))
117*387f9dfdSAndroid Build Coastguard Worker
118*387f9dfdSAndroid Build Coastguard Worker# Print header
119*387f9dfdSAndroid Build Coastguard Workerprint("Tracing... Hit Ctrl-C to end.")
120*387f9dfdSAndroid Build Coastguard Workerprint("%-18s %-10s %-32s %-32s %16s %16s %16s" % ("time(s)", "id", "input", "output", "start (ns)", "end (ns)", "duration (us)"))
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard Worker# Output latency events
123*387f9dfdSAndroid Build Coastguard Workerbpf_ctx["operation_event"].open_perf_buffer(print_event)
124*387f9dfdSAndroid Build Coastguard Workerwhile 1:
125*387f9dfdSAndroid Build Coastguard Worker    bpf_ctx.perf_buffer_poll()
126