xref: /aosp_15_r20/external/bcc/tools/tcprtt.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports
3*387f9dfdSAndroid Build Coastguard Worker#
4*387f9dfdSAndroid Build Coastguard Worker# tcprtt    Summarize TCP RTT as a histogram. For Linux, uses BCC, eBPF.
5*387f9dfdSAndroid Build Coastguard Worker#
6*387f9dfdSAndroid Build Coastguard Worker# USAGE: tcprtt [-h] [-T] [-D] [-m] [-i INTERVAL] [-d DURATION]
7*387f9dfdSAndroid Build Coastguard Worker#           [-p LPORT] [-P RPORT] [-a LADDR] [-A RADDR] [-b] [-B] [-e]
8*387f9dfdSAndroid Build Coastguard Worker#           [-4 | -6]
9*387f9dfdSAndroid Build Coastguard Worker#
10*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2020 zhenwei pi
11*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
12*387f9dfdSAndroid Build Coastguard Worker#
13*387f9dfdSAndroid Build Coastguard Worker# 23-AUG-2020  zhenwei pi  Created this.
14*387f9dfdSAndroid Build Coastguard Worker
15*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
16*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
17*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime
18*387f9dfdSAndroid Build Coastguard Workerfrom socket import inet_ntop, inet_pton, AF_INET, AF_INET6
19*387f9dfdSAndroid Build Coastguard Workerimport socket, struct
20*387f9dfdSAndroid Build Coastguard Workerimport argparse
21*387f9dfdSAndroid Build Coastguard Workerimport ctypes
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard Worker# arguments
24*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
25*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt            # summarize TCP RTT
26*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -i 1 -d 10 # print 1 second summaries, 10 times
27*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -m -T      # summarize in millisecond, and timestamps
28*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -p         # filter for local port
29*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -P         # filter for remote port
30*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -a         # filter for local address
31*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -A         # filter for remote address
32*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -b         # show sockets histogram by local address
33*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -B         # show sockets histogram by remote address
34*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -D         # show debug bpf text
35*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -e         # show extension summary(average)
36*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -4         # trace only IPv4 family
37*387f9dfdSAndroid Build Coastguard Worker    ./tcprtt -6         # trace only IPv6 family
38*387f9dfdSAndroid Build Coastguard Worker"""
39*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
40*387f9dfdSAndroid Build Coastguard Worker    description="Summarize TCP RTT as a histogram",
41*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
42*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
43*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-i", "--interval",
44*387f9dfdSAndroid Build Coastguard Worker    help="summary interval, seconds")
45*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-d", "--duration", type=int, default=99999,
46*387f9dfdSAndroid Build Coastguard Worker    help="total duration of trace, seconds")
47*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--timestamp", action="store_true",
48*387f9dfdSAndroid Build Coastguard Worker    help="include timestamp on output")
49*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-m", "--milliseconds", action="store_true",
50*387f9dfdSAndroid Build Coastguard Worker    help="millisecond histogram")
51*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--lport",
52*387f9dfdSAndroid Build Coastguard Worker    help="filter for local port")
53*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-P", "--rport",
54*387f9dfdSAndroid Build Coastguard Worker    help="filter for remote port")
55*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-a", "--laddr",
56*387f9dfdSAndroid Build Coastguard Worker    help="filter for local address")
57*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-A", "--raddr",
58*387f9dfdSAndroid Build Coastguard Worker    help="filter for remote address")
59*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-b", "--byladdr", action="store_true",
60*387f9dfdSAndroid Build Coastguard Worker    help="show sockets histogram by local address")
61*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-B", "--byraddr", action="store_true",
62*387f9dfdSAndroid Build Coastguard Worker    help="show sockets histogram by remote address")
63*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-e", "--extension", action="store_true",
64*387f9dfdSAndroid Build Coastguard Worker    help="show extension summary(average)")
65*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-D", "--debug", action="store_true",
66*387f9dfdSAndroid Build Coastguard Worker    help="print BPF program before starting (for debugging purposes)")
67*387f9dfdSAndroid Build Coastguard Workergroup = parser.add_mutually_exclusive_group()
68*387f9dfdSAndroid Build Coastguard Workergroup.add_argument("-4", "--ipv4", action="store_true",
69*387f9dfdSAndroid Build Coastguard Worker    help="trace IPv4 family only")
70*387f9dfdSAndroid Build Coastguard Workergroup.add_argument("-6", "--ipv6", action="store_true",
71*387f9dfdSAndroid Build Coastguard Worker    help="trace IPv6 family only")
72*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
73*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
74*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
75*387f9dfdSAndroid Build Coastguard Workerif not args.interval:
76*387f9dfdSAndroid Build Coastguard Worker    args.interval = args.duration
77*387f9dfdSAndroid Build Coastguard Worker
78*387f9dfdSAndroid Build Coastguard Worker# define BPF program
79*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
80*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
81*387f9dfdSAndroid Build Coastguard Worker#include <linux/tcp.h>
82*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h>
83*387f9dfdSAndroid Build Coastguard Worker#include <net/inet_sock.h>
84*387f9dfdSAndroid Build Coastguard Worker#include <bcc/proto.h>
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Workertypedef struct sock_key {
87*387f9dfdSAndroid Build Coastguard Worker    u64 addr;
88*387f9dfdSAndroid Build Coastguard Worker    u64 slot;
89*387f9dfdSAndroid Build Coastguard Worker} sock_key_t;
90*387f9dfdSAndroid Build Coastguard Worker
91*387f9dfdSAndroid Build Coastguard Workertypedef struct sock_latenty {
92*387f9dfdSAndroid Build Coastguard Worker    u64 latency;
93*387f9dfdSAndroid Build Coastguard Worker    u64 count;
94*387f9dfdSAndroid Build Coastguard Worker} sock_latency_t;
95*387f9dfdSAndroid Build Coastguard Worker
96*387f9dfdSAndroid Build Coastguard WorkerBPF_HISTOGRAM(hist_srtt, sock_key_t);
97*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(latency, u64, sock_latency_t);
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Workerint trace_tcp_rcv(struct pt_regs *ctx, struct sock *sk, struct sk_buff *skb)
100*387f9dfdSAndroid Build Coastguard Worker{
101*387f9dfdSAndroid Build Coastguard Worker    struct tcp_sock *ts = (struct tcp_sock *)sk;
102*387f9dfdSAndroid Build Coastguard Worker    u32 srtt = ts->srtt_us >> 3;
103*387f9dfdSAndroid Build Coastguard Worker    const struct inet_sock *inet = (struct inet_sock *)sk;
104*387f9dfdSAndroid Build Coastguard Worker
105*387f9dfdSAndroid Build Coastguard Worker    /* filters */
106*387f9dfdSAndroid Build Coastguard Worker    u16 sport = 0;
107*387f9dfdSAndroid Build Coastguard Worker    u16 dport = 0;
108*387f9dfdSAndroid Build Coastguard Worker    u32 saddr = 0;
109*387f9dfdSAndroid Build Coastguard Worker    u32 daddr = 0;
110*387f9dfdSAndroid Build Coastguard Worker    __u8 saddr6[16];
111*387f9dfdSAndroid Build Coastguard Worker    __u8 daddr6[16];
112*387f9dfdSAndroid Build Coastguard Worker    u16 family = 0;
113*387f9dfdSAndroid Build Coastguard Worker
114*387f9dfdSAndroid Build Coastguard Worker    /* for histogram */
115*387f9dfdSAndroid Build Coastguard Worker    sock_key_t key;
116*387f9dfdSAndroid Build Coastguard Worker
117*387f9dfdSAndroid Build Coastguard Worker    /* for avg latency, if no saddr/daddr specified, use 0(addr) as key */
118*387f9dfdSAndroid Build Coastguard Worker    u64 addr = 0;
119*387f9dfdSAndroid Build Coastguard Worker
120*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&sport, sizeof(sport), (void *)&inet->inet_sport);
121*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&dport, sizeof(dport), (void *)&inet->inet_dport);
122*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&family, sizeof(family), (void *)&sk->__sk_common.skc_family);
123*387f9dfdSAndroid Build Coastguard Worker    if (family == AF_INET6) {
124*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel(&saddr6, sizeof(saddr6),
125*387f9dfdSAndroid Build Coastguard Worker                              (void *)&sk->__sk_common.skc_v6_rcv_saddr.s6_addr);
126*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel(&daddr6, sizeof(daddr6),
127*387f9dfdSAndroid Build Coastguard Worker                              (void *)&sk->__sk_common.skc_v6_daddr.s6_addr);
128*387f9dfdSAndroid Build Coastguard Worker    } else {
129*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel(&saddr, sizeof(saddr), (void *)&inet->inet_saddr);
130*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel(&daddr, sizeof(daddr), (void *)&inet->inet_daddr);
131*387f9dfdSAndroid Build Coastguard Worker    }
132*387f9dfdSAndroid Build Coastguard Worker
133*387f9dfdSAndroid Build Coastguard Worker    LPORTFILTER
134*387f9dfdSAndroid Build Coastguard Worker    RPORTFILTER
135*387f9dfdSAndroid Build Coastguard Worker    LADDRFILTER
136*387f9dfdSAndroid Build Coastguard Worker    RADDRFILTER
137*387f9dfdSAndroid Build Coastguard Worker    FAMILYFILTER
138*387f9dfdSAndroid Build Coastguard Worker
139*387f9dfdSAndroid Build Coastguard Worker    FACTOR
140*387f9dfdSAndroid Build Coastguard Worker
141*387f9dfdSAndroid Build Coastguard Worker    STORE_HIST
142*387f9dfdSAndroid Build Coastguard Worker    key.slot = bpf_log2l(srtt);
143*387f9dfdSAndroid Build Coastguard Worker    hist_srtt.atomic_increment(key);
144*387f9dfdSAndroid Build Coastguard Worker
145*387f9dfdSAndroid Build Coastguard Worker    STORE_LATENCY
146*387f9dfdSAndroid Build Coastguard Worker
147*387f9dfdSAndroid Build Coastguard Worker    return 0;
148*387f9dfdSAndroid Build Coastguard Worker}
149*387f9dfdSAndroid Build Coastguard Worker"""
150*387f9dfdSAndroid Build Coastguard Worker
151*387f9dfdSAndroid Build Coastguard Worker# filter for local port
152*387f9dfdSAndroid Build Coastguard Workerif args.lport:
153*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('LPORTFILTER',
154*387f9dfdSAndroid Build Coastguard Worker        """if (ntohs(sport) != %d)
155*387f9dfdSAndroid Build Coastguard Worker        return 0;""" % int(args.lport))
156*387f9dfdSAndroid Build Coastguard Workerelse:
157*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('LPORTFILTER', '')
158*387f9dfdSAndroid Build Coastguard Worker
159*387f9dfdSAndroid Build Coastguard Worker# filter for remote port
160*387f9dfdSAndroid Build Coastguard Workerif args.rport:
161*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('RPORTFILTER',
162*387f9dfdSAndroid Build Coastguard Worker        """if (ntohs(dport) != %d)
163*387f9dfdSAndroid Build Coastguard Worker        return 0;""" % int(args.rport))
164*387f9dfdSAndroid Build Coastguard Workerelse:
165*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('RPORTFILTER', '')
166*387f9dfdSAndroid Build Coastguard Worker
167*387f9dfdSAndroid Build Coastguard Workerdef addrfilter(addr, src_or_dest):
168*387f9dfdSAndroid Build Coastguard Worker    try:
169*387f9dfdSAndroid Build Coastguard Worker        naddr = socket.inet_pton(AF_INET, addr)
170*387f9dfdSAndroid Build Coastguard Worker    except:
171*387f9dfdSAndroid Build Coastguard Worker        naddr = socket.inet_pton(AF_INET6, addr)
172*387f9dfdSAndroid Build Coastguard Worker        s = ('\\' + struct.unpack("=16s", naddr)[0].hex('\\')).replace('\\', '\\x')
173*387f9dfdSAndroid Build Coastguard Worker        filter = "if (memcmp(%s6, \"%s\", 16)) return 0;" % (src_or_dest, s)
174*387f9dfdSAndroid Build Coastguard Worker    else:
175*387f9dfdSAndroid Build Coastguard Worker        filter = "if (%s != %d) return 0;" % (src_or_dest, struct.unpack("=I", naddr)[0])
176*387f9dfdSAndroid Build Coastguard Worker    return filter
177*387f9dfdSAndroid Build Coastguard Worker
178*387f9dfdSAndroid Build Coastguard Worker# filter for local address
179*387f9dfdSAndroid Build Coastguard Workerif args.laddr:
180*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('LADDRFILTER', addrfilter(args.laddr, 'saddr'))
181*387f9dfdSAndroid Build Coastguard Workerelse:
182*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('LADDRFILTER', '')
183*387f9dfdSAndroid Build Coastguard Worker
184*387f9dfdSAndroid Build Coastguard Worker# filter for remote address
185*387f9dfdSAndroid Build Coastguard Workerif args.raddr:
186*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('RADDRFILTER', addrfilter(args.raddr, 'daddr'))
187*387f9dfdSAndroid Build Coastguard Workerelse:
188*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('RADDRFILTER', '')
189*387f9dfdSAndroid Build Coastguard Workerif args.ipv4:
190*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FAMILYFILTER',
191*387f9dfdSAndroid Build Coastguard Worker        'if (family != AF_INET) { return 0; }')
192*387f9dfdSAndroid Build Coastguard Workerelif args.ipv6:
193*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FAMILYFILTER',
194*387f9dfdSAndroid Build Coastguard Worker        'if (family != AF_INET6) { return 0; }')
195*387f9dfdSAndroid Build Coastguard Workerelse:
196*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FAMILYFILTER', '')
197*387f9dfdSAndroid Build Coastguard Worker# show msecs or usecs[default]
198*387f9dfdSAndroid Build Coastguard Workerif args.milliseconds:
199*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FACTOR', 'srtt /= 1000;')
200*387f9dfdSAndroid Build Coastguard Worker    label = "msecs"
201*387f9dfdSAndroid Build Coastguard Workerelse:
202*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FACTOR', '')
203*387f9dfdSAndroid Build Coastguard Worker    label = "usecs"
204*387f9dfdSAndroid Build Coastguard Worker
205*387f9dfdSAndroid Build Coastguard Workerprint_header = "srtt"
206*387f9dfdSAndroid Build Coastguard Worker# show byladdr/byraddr histogram
207*387f9dfdSAndroid Build Coastguard Workerif args.byladdr:
208*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('STORE_HIST', 'key.addr = addr = saddr;')
209*387f9dfdSAndroid Build Coastguard Worker    print_header = "Local Address"
210*387f9dfdSAndroid Build Coastguard Workerelif args.byraddr:
211*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('STORE_HIST', 'key.addr = addr = daddr;')
212*387f9dfdSAndroid Build Coastguard Worker    print_header = "Remote Addres"
213*387f9dfdSAndroid Build Coastguard Workerelse:
214*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('STORE_HIST', 'key.addr = addr = 0;')
215*387f9dfdSAndroid Build Coastguard Worker    print_header = "All Addresses"
216*387f9dfdSAndroid Build Coastguard Worker
217*387f9dfdSAndroid Build Coastguard Workerif args.extension:
218*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('STORE_LATENCY', """
219*387f9dfdSAndroid Build Coastguard Worker    sock_latency_t newlat = {0};
220*387f9dfdSAndroid Build Coastguard Worker    sock_latency_t *lat;
221*387f9dfdSAndroid Build Coastguard Worker    lat = latency.lookup(&addr);
222*387f9dfdSAndroid Build Coastguard Worker    if (!lat) {
223*387f9dfdSAndroid Build Coastguard Worker        newlat.latency += srtt;
224*387f9dfdSAndroid Build Coastguard Worker        newlat.count += 1;
225*387f9dfdSAndroid Build Coastguard Worker        latency.update(&addr, &newlat);
226*387f9dfdSAndroid Build Coastguard Worker    } else {
227*387f9dfdSAndroid Build Coastguard Worker        lat->latency +=srtt;
228*387f9dfdSAndroid Build Coastguard Worker        lat->count += 1;
229*387f9dfdSAndroid Build Coastguard Worker    }
230*387f9dfdSAndroid Build Coastguard Worker    """)
231*387f9dfdSAndroid Build Coastguard Workerelse:
232*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('STORE_LATENCY', '')
233*387f9dfdSAndroid Build Coastguard Worker
234*387f9dfdSAndroid Build Coastguard Worker# debug/dump ebpf enable or not
235*387f9dfdSAndroid Build Coastguard Workerif args.debug or args.ebpf:
236*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
237*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
238*387f9dfdSAndroid Build Coastguard Worker        exit()
239*387f9dfdSAndroid Build Coastguard Worker
240*387f9dfdSAndroid Build Coastguard Worker# load BPF program
241*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
242*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="tcp_rcv_established", fn_name="trace_tcp_rcv")
243*387f9dfdSAndroid Build Coastguard Worker
244*387f9dfdSAndroid Build Coastguard Workerprint("Tracing TCP RTT... Hit Ctrl-C to end.")
245*387f9dfdSAndroid Build Coastguard Worker
246*387f9dfdSAndroid Build Coastguard Workerdef print_section(addr):
247*387f9dfdSAndroid Build Coastguard Worker    addrstr = "*******"
248*387f9dfdSAndroid Build Coastguard Worker    if (addr):
249*387f9dfdSAndroid Build Coastguard Worker        addrstr = inet_ntop(AF_INET, struct.pack("I", addr))
250*387f9dfdSAndroid Build Coastguard Worker
251*387f9dfdSAndroid Build Coastguard Worker    avglat = ""
252*387f9dfdSAndroid Build Coastguard Worker    if args.extension:
253*387f9dfdSAndroid Build Coastguard Worker        lats = b.get_table("latency")
254*387f9dfdSAndroid Build Coastguard Worker        lat = lats[ctypes.c_ulong(addr)]
255*387f9dfdSAndroid Build Coastguard Worker        avglat = " [AVG %d]" % (lat.latency / lat.count)
256*387f9dfdSAndroid Build Coastguard Worker
257*387f9dfdSAndroid Build Coastguard Worker    return addrstr + avglat
258*387f9dfdSAndroid Build Coastguard Worker
259*387f9dfdSAndroid Build Coastguard Worker# output
260*387f9dfdSAndroid Build Coastguard Workerexiting = 0 if args.interval else 1
261*387f9dfdSAndroid Build Coastguard Workerdist = b.get_table("hist_srtt")
262*387f9dfdSAndroid Build Coastguard Workerlathash = b.get_table("latency")
263*387f9dfdSAndroid Build Coastguard Workerseconds = 0
264*387f9dfdSAndroid Build Coastguard Workerwhile (1):
265*387f9dfdSAndroid Build Coastguard Worker    try:
266*387f9dfdSAndroid Build Coastguard Worker        sleep(int(args.interval))
267*387f9dfdSAndroid Build Coastguard Worker        seconds = seconds + int(args.interval)
268*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
269*387f9dfdSAndroid Build Coastguard Worker        exiting = 1
270*387f9dfdSAndroid Build Coastguard Worker
271*387f9dfdSAndroid Build Coastguard Worker    print()
272*387f9dfdSAndroid Build Coastguard Worker    if args.timestamp:
273*387f9dfdSAndroid Build Coastguard Worker        print("%-8s\n" % strftime("%H:%M:%S"), end="")
274*387f9dfdSAndroid Build Coastguard Worker
275*387f9dfdSAndroid Build Coastguard Worker    dist.print_log2_hist(label, section_header=print_header, section_print_fn=print_section)
276*387f9dfdSAndroid Build Coastguard Worker    dist.clear()
277*387f9dfdSAndroid Build Coastguard Worker    lathash.clear()
278*387f9dfdSAndroid Build Coastguard Worker
279*387f9dfdSAndroid Build Coastguard Worker    if exiting or seconds >= args.duration:
280*387f9dfdSAndroid Build Coastguard Worker        exit()
281