xref: /aosp_15_r20/external/bcc/tools/gethostlatency.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# gethostlatency  Show latency for getaddrinfo/gethostbyname[2] calls.
4*387f9dfdSAndroid Build Coastguard Worker#                 For Linux, uses BCC, eBPF. Embedded C.
5*387f9dfdSAndroid Build Coastguard Worker#
6*387f9dfdSAndroid Build Coastguard Worker# This can be useful for identifying DNS latency, by identifying which
7*387f9dfdSAndroid Build Coastguard Worker# remote host name lookups were slow, and by how much.
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# This uses dynamic tracing of user-level functions and registers, and may
10*387f9dfdSAndroid Build Coastguard Worker# need modifications to match your software and processor architecture.
11*387f9dfdSAndroid Build Coastguard Worker#
12*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
13*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
14*387f9dfdSAndroid Build Coastguard Worker#
15*387f9dfdSAndroid Build Coastguard Worker# 28-Jan-2016    Brendan Gregg   Created this.
16*387f9dfdSAndroid Build Coastguard Worker# 30-Mar-2016   Allan McAleavy updated for BPF_PERF_OUTPUT
17*387f9dfdSAndroid Build Coastguard Worker
18*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
19*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
20*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime
21*387f9dfdSAndroid Build Coastguard Workerimport argparse
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
24*387f9dfdSAndroid Build Coastguard Worker    ./gethostlatency           # time getaddrinfo/gethostbyname[2] calls
25*387f9dfdSAndroid Build Coastguard Worker    ./gethostlatency -p 181    # only trace PID 181
26*387f9dfdSAndroid Build Coastguard Worker"""
27*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
28*387f9dfdSAndroid Build Coastguard Worker    description="Show latency for getaddrinfo/gethostbyname[2] calls",
29*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
30*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
31*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", help="trace this PID only", type=int,
32*387f9dfdSAndroid Build Coastguard Worker    default=-1)
33*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
34*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
35*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
36*387f9dfdSAndroid Build Coastguard Worker
37*387f9dfdSAndroid Build Coastguard Worker# load BPF program
38*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
39*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
40*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
41*387f9dfdSAndroid Build Coastguard Worker
42*387f9dfdSAndroid Build Coastguard Workerstruct val_t {
43*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
44*387f9dfdSAndroid Build Coastguard Worker    char comm[TASK_COMM_LEN];
45*387f9dfdSAndroid Build Coastguard Worker    char host[80];
46*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
47*387f9dfdSAndroid Build Coastguard Worker};
48*387f9dfdSAndroid Build Coastguard Worker
49*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
50*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
51*387f9dfdSAndroid Build Coastguard Worker    u64 delta;
52*387f9dfdSAndroid Build Coastguard Worker    char comm[TASK_COMM_LEN];
53*387f9dfdSAndroid Build Coastguard Worker    char host[80];
54*387f9dfdSAndroid Build Coastguard Worker};
55*387f9dfdSAndroid Build Coastguard Worker
56*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, u32, struct val_t);
57*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Workerint do_entry(struct pt_regs *ctx) {
60*387f9dfdSAndroid Build Coastguard Worker    if (!PT_REGS_PARM1(ctx))
61*387f9dfdSAndroid Build Coastguard Worker        return 0;
62*387f9dfdSAndroid Build Coastguard Worker
63*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
64*387f9dfdSAndroid Build Coastguard Worker    u64 pid_tgid = bpf_get_current_pid_tgid();
65*387f9dfdSAndroid Build Coastguard Worker    u32 pid = pid_tgid >> 32;
66*387f9dfdSAndroid Build Coastguard Worker    u32 tid = (u32)pid_tgid;
67*387f9dfdSAndroid Build Coastguard Worker
68*387f9dfdSAndroid Build Coastguard Worker    if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
69*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_user(&val.host, sizeof(val.host),
70*387f9dfdSAndroid Build Coastguard Worker                       (void *)PT_REGS_PARM1(ctx));
71*387f9dfdSAndroid Build Coastguard Worker        val.pid = pid;
72*387f9dfdSAndroid Build Coastguard Worker        val.ts = bpf_ktime_get_ns();
73*387f9dfdSAndroid Build Coastguard Worker        start.update(&tid, &val);
74*387f9dfdSAndroid Build Coastguard Worker    }
75*387f9dfdSAndroid Build Coastguard Worker
76*387f9dfdSAndroid Build Coastguard Worker    return 0;
77*387f9dfdSAndroid Build Coastguard Worker}
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard Workerint do_return(struct pt_regs *ctx) {
80*387f9dfdSAndroid Build Coastguard Worker    struct val_t *valp;
81*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
82*387f9dfdSAndroid Build Coastguard Worker    u64 delta;
83*387f9dfdSAndroid Build Coastguard Worker    u64 pid_tgid = bpf_get_current_pid_tgid();
84*387f9dfdSAndroid Build Coastguard Worker    u32 tid = (u32)pid_tgid;
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Worker    u64 tsp = bpf_ktime_get_ns();
87*387f9dfdSAndroid Build Coastguard Worker
88*387f9dfdSAndroid Build Coastguard Worker    valp = start.lookup(&tid);
89*387f9dfdSAndroid Build Coastguard Worker    if (valp == 0)
90*387f9dfdSAndroid Build Coastguard Worker        return 0;       // missed start
91*387f9dfdSAndroid Build Coastguard Worker
92*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm);
93*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&data.host, sizeof(data.host), (void *)valp->host);
94*387f9dfdSAndroid Build Coastguard Worker    data.pid = valp->pid;
95*387f9dfdSAndroid Build Coastguard Worker    data.delta = tsp - valp->ts;
96*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
97*387f9dfdSAndroid Build Coastguard Worker    start.delete(&tid);
98*387f9dfdSAndroid Build Coastguard Worker    return 0;
99*387f9dfdSAndroid Build Coastguard Worker}
100*387f9dfdSAndroid Build Coastguard Worker"""
101*387f9dfdSAndroid Build Coastguard Workerif args.ebpf:
102*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
103*387f9dfdSAndroid Build Coastguard Worker    exit()
104*387f9dfdSAndroid Build Coastguard Worker
105*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
106*387f9dfdSAndroid Build Coastguard Workerb.attach_uprobe(name="c", sym="getaddrinfo", fn_name="do_entry", pid=args.pid)
107*387f9dfdSAndroid Build Coastguard Workerb.attach_uprobe(name="c", sym="gethostbyname", fn_name="do_entry",
108*387f9dfdSAndroid Build Coastguard Worker                pid=args.pid)
109*387f9dfdSAndroid Build Coastguard Workerb.attach_uprobe(name="c", sym="gethostbyname2", fn_name="do_entry",
110*387f9dfdSAndroid Build Coastguard Worker                pid=args.pid)
111*387f9dfdSAndroid Build Coastguard Workerb.attach_uretprobe(name="c", sym="getaddrinfo", fn_name="do_return",
112*387f9dfdSAndroid Build Coastguard Worker                   pid=args.pid)
113*387f9dfdSAndroid Build Coastguard Workerb.attach_uretprobe(name="c", sym="gethostbyname", fn_name="do_return",
114*387f9dfdSAndroid Build Coastguard Worker                   pid=args.pid)
115*387f9dfdSAndroid Build Coastguard Workerb.attach_uretprobe(name="c", sym="gethostbyname2", fn_name="do_return",
116*387f9dfdSAndroid Build Coastguard Worker                   pid=args.pid)
117*387f9dfdSAndroid Build Coastguard Worker
118*387f9dfdSAndroid Build Coastguard Worker# header
119*387f9dfdSAndroid Build Coastguard Workerprint("%-9s %-7s %-16s %10s %s" % ("TIME", "PID", "COMM", "LATms", "HOST"))
120*387f9dfdSAndroid Build Coastguard Worker
121*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
122*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
123*387f9dfdSAndroid Build Coastguard Worker    print("%-9s %-7d %-16s %10.2f %s" % (strftime("%H:%M:%S"), event.pid,
124*387f9dfdSAndroid Build Coastguard Worker        event.comm.decode('utf-8', 'replace'), (float(event.delta) / 1000000),
125*387f9dfdSAndroid Build Coastguard Worker        event.host.decode('utf-8', 'replace')))
126*387f9dfdSAndroid Build Coastguard Worker
127*387f9dfdSAndroid Build Coastguard Worker# loop with callback to print_event
128*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event)
129*387f9dfdSAndroid Build Coastguard Workerwhile 1:
130*387f9dfdSAndroid Build Coastguard Worker    try:
131*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
132*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
133*387f9dfdSAndroid Build Coastguard Worker        exit()
134