xref: /aosp_15_r20/external/bcc/tools/biolatpcts.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# biolatpcts.py  Monitor IO latency distribution of a block device.
4*387f9dfdSAndroid Build Coastguard Worker#
5*387f9dfdSAndroid Build Coastguard Worker#  $ ./biolatpcts.py /dev/nvme0n1
6*387f9dfdSAndroid Build Coastguard Worker#  nvme0n1    p1    p5   p10   p16   p25   p50   p75   p84   p90   p95   p99  p100
7*387f9dfdSAndroid Build Coastguard Worker#  read     95us 175us 305us 515us 895us 985us 995us 1.5ms 2.5ms 3.5ms 4.5ms  10ms
8*387f9dfdSAndroid Build Coastguard Worker#  write     5us   5us   5us  15us  25us 135us 765us 855us 885us 895us 965us 1.5ms
9*387f9dfdSAndroid Build Coastguard Worker#  discard   5us   5us   5us   5us 135us 145us 165us 205us 385us 875us 1.5ms 2.5ms
10*387f9dfdSAndroid Build Coastguard Worker#  flush     5us   5us   5us   5us   5us   5us   5us   5us   5us 1.5ms 4.5ms 5.5ms
11*387f9dfdSAndroid Build Coastguard Worker#
12*387f9dfdSAndroid Build Coastguard Worker# Copyright (C) 2020 Tejun Heo <[email protected]>
13*387f9dfdSAndroid Build Coastguard Worker# Copyright (C) 2020 Facebook
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
18*387f9dfdSAndroid Build Coastguard Workerfrom threading import Event
19*387f9dfdSAndroid Build Coastguard Workerimport argparse
20*387f9dfdSAndroid Build Coastguard Workerimport json
21*387f9dfdSAndroid Build Coastguard Workerimport sys
22*387f9dfdSAndroid Build Coastguard Workerimport os
23*387f9dfdSAndroid Build Coastguard Workerimport signal
24*387f9dfdSAndroid Build Coastguard Worker
25*387f9dfdSAndroid Build Coastguard Workerdescription = """
26*387f9dfdSAndroid Build Coastguard WorkerMonitor IO latency distribution of a block device
27*387f9dfdSAndroid Build Coastguard Worker"""
28*387f9dfdSAndroid Build Coastguard Worker
29*387f9dfdSAndroid Build Coastguard Workerepilog = """
30*387f9dfdSAndroid Build Coastguard WorkerWhen interval is infinite, biolatpcts will print out result once the
31*387f9dfdSAndroid Build Coastguard Workerinitialization is complete to indicate readiness. After initialized,
32*387f9dfdSAndroid Build Coastguard Workerbiolatpcts will output whenever it receives SIGUSR1/2 and before exiting on
33*387f9dfdSAndroid Build Coastguard WorkerSIGINT, SIGTERM or SIGHUP.
34*387f9dfdSAndroid Build Coastguard Worker
35*387f9dfdSAndroid Build Coastguard WorkerSIGUSR1 starts a new period after reporting. SIGUSR2 doesn't and can be used
36*387f9dfdSAndroid Build Coastguard Workerto monitor progress without affecting accumulation of data points. They can
37*387f9dfdSAndroid Build Coastguard Workerbe used to obtain latency distribution between two arbitrary events and
38*387f9dfdSAndroid Build Coastguard Workermonitor progress inbetween.
39*387f9dfdSAndroid Build Coastguard Worker"""
40*387f9dfdSAndroid Build Coastguard Worker
41*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(description = description, epilog = epilog,
42*387f9dfdSAndroid Build Coastguard Worker                                 formatter_class = argparse.ArgumentDefaultsHelpFormatter)
43*387f9dfdSAndroid Build Coastguard Workerparser.add_argument('dev', metavar='DEV', type=str,
44*387f9dfdSAndroid Build Coastguard Worker                    help='Target block device (/dev/DEVNAME, DEVNAME or MAJ:MIN)')
45*387f9dfdSAndroid Build Coastguard Workerparser.add_argument('-i', '--interval', type=int, default=3,
46*387f9dfdSAndroid Build Coastguard Worker                    help='Report interval (0: exit after startup, -1: infinite)')
47*387f9dfdSAndroid Build Coastguard Workerparser.add_argument('-w', '--which', choices=['from-rq-alloc', 'after-rq-alloc', 'on-device'],
48*387f9dfdSAndroid Build Coastguard Worker                    default='on-device', help='Which latency to measure')
49*387f9dfdSAndroid Build Coastguard Workerparser.add_argument('-p', '--pcts', metavar='PCT,...', type=str,
50*387f9dfdSAndroid Build Coastguard Worker                    default='1,5,10,16,25,50,75,84,90,95,99,100',
51*387f9dfdSAndroid Build Coastguard Worker                    help='Percentiles to calculate')
52*387f9dfdSAndroid Build Coastguard Workerparser.add_argument('-j', '--json', action='store_true',
53*387f9dfdSAndroid Build Coastguard Worker                    help='Output in json')
54*387f9dfdSAndroid Build Coastguard Workerparser.add_argument('--verbose', '-v', action='count', default = 0)
55*387f9dfdSAndroid Build Coastguard Worker
56*387f9dfdSAndroid Build Coastguard Workerbpf_source = """
57*387f9dfdSAndroid Build Coastguard Worker#include <linux/blk_types.h>
58*387f9dfdSAndroid Build Coastguard Worker#include <linux/blkdev.h>
59*387f9dfdSAndroid Build Coastguard Worker#include <linux/blk-mq.h>
60*387f9dfdSAndroid Build Coastguard Worker#include <linux/time64.h>
61*387f9dfdSAndroid Build Coastguard Worker
62*387f9dfdSAndroid Build Coastguard WorkerBPF_PERCPU_ARRAY(rwdf_100ms, u64, 400);
63*387f9dfdSAndroid Build Coastguard WorkerBPF_PERCPU_ARRAY(rwdf_1ms, u64, 400);
64*387f9dfdSAndroid Build Coastguard WorkerBPF_PERCPU_ARRAY(rwdf_10us, u64, 400);
65*387f9dfdSAndroid Build Coastguard Worker
66*387f9dfdSAndroid Build Coastguard WorkerRAW_TRACEPOINT_PROBE(block_rq_complete)
67*387f9dfdSAndroid Build Coastguard Worker{
68*387f9dfdSAndroid Build Coastguard Worker        // TP_PROTO(struct request *rq, blk_status_t error, unsigned int nr_bytes)
69*387f9dfdSAndroid Build Coastguard Worker        struct request *rq = (void *)ctx->args[0];
70*387f9dfdSAndroid Build Coastguard Worker        unsigned int cmd_flags;
71*387f9dfdSAndroid Build Coastguard Worker        u64 dur;
72*387f9dfdSAndroid Build Coastguard Worker        size_t base, slot;
73*387f9dfdSAndroid Build Coastguard Worker
74*387f9dfdSAndroid Build Coastguard Worker        if (!rq->__START_TIME_FIELD__)
75*387f9dfdSAndroid Build Coastguard Worker                return 0;
76*387f9dfdSAndroid Build Coastguard Worker
77*387f9dfdSAndroid Build Coastguard Worker        if (!rq->__RQ_DISK__ ||
78*387f9dfdSAndroid Build Coastguard Worker            rq->__RQ_DISK__->major != __MAJOR__ ||
79*387f9dfdSAndroid Build Coastguard Worker            rq->__RQ_DISK__->first_minor != __MINOR__)
80*387f9dfdSAndroid Build Coastguard Worker                return 0;
81*387f9dfdSAndroid Build Coastguard Worker
82*387f9dfdSAndroid Build Coastguard Worker        cmd_flags = rq->cmd_flags;
83*387f9dfdSAndroid Build Coastguard Worker        switch (cmd_flags & REQ_OP_MASK) {
84*387f9dfdSAndroid Build Coastguard Worker        case REQ_OP_READ:
85*387f9dfdSAndroid Build Coastguard Worker                base = 0;
86*387f9dfdSAndroid Build Coastguard Worker                break;
87*387f9dfdSAndroid Build Coastguard Worker        case REQ_OP_WRITE:
88*387f9dfdSAndroid Build Coastguard Worker                base = 100;
89*387f9dfdSAndroid Build Coastguard Worker                break;
90*387f9dfdSAndroid Build Coastguard Worker        case REQ_OP_DISCARD:
91*387f9dfdSAndroid Build Coastguard Worker                base = 200;
92*387f9dfdSAndroid Build Coastguard Worker                break;
93*387f9dfdSAndroid Build Coastguard Worker        case REQ_OP_FLUSH:
94*387f9dfdSAndroid Build Coastguard Worker                base = 300;
95*387f9dfdSAndroid Build Coastguard Worker                break;
96*387f9dfdSAndroid Build Coastguard Worker        default:
97*387f9dfdSAndroid Build Coastguard Worker                return 0;
98*387f9dfdSAndroid Build Coastguard Worker        }
99*387f9dfdSAndroid Build Coastguard Worker
100*387f9dfdSAndroid Build Coastguard Worker        dur = bpf_ktime_get_ns() - rq->__START_TIME_FIELD__;
101*387f9dfdSAndroid Build Coastguard Worker
102*387f9dfdSAndroid Build Coastguard Worker        slot = min_t(size_t, div_u64(dur, 100 * NSEC_PER_MSEC), 99);
103*387f9dfdSAndroid Build Coastguard Worker        rwdf_100ms.increment(base + slot);
104*387f9dfdSAndroid Build Coastguard Worker        if (slot)
105*387f9dfdSAndroid Build Coastguard Worker                return 0;
106*387f9dfdSAndroid Build Coastguard Worker
107*387f9dfdSAndroid Build Coastguard Worker        slot = min_t(size_t, div_u64(dur, NSEC_PER_MSEC), 99);
108*387f9dfdSAndroid Build Coastguard Worker        rwdf_1ms.increment(base + slot);
109*387f9dfdSAndroid Build Coastguard Worker        if (slot)
110*387f9dfdSAndroid Build Coastguard Worker                return 0;
111*387f9dfdSAndroid Build Coastguard Worker
112*387f9dfdSAndroid Build Coastguard Worker        slot = min_t(size_t, div_u64(dur, 10 * NSEC_PER_USEC), 99);
113*387f9dfdSAndroid Build Coastguard Worker        rwdf_10us.increment(base + slot);
114*387f9dfdSAndroid Build Coastguard Worker        return 0;
115*387f9dfdSAndroid Build Coastguard Worker}
116*387f9dfdSAndroid Build Coastguard Worker"""
117*387f9dfdSAndroid Build Coastguard Worker
118*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
119*387f9dfdSAndroid Build Coastguard Workerargs.pcts = args.pcts.split(',')
120*387f9dfdSAndroid Build Coastguard Workerargs.pcts.sort(key=lambda x: float(x))
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard Workertry:
123*387f9dfdSAndroid Build Coastguard Worker    major = int(args.dev.split(':')[0])
124*387f9dfdSAndroid Build Coastguard Worker    minor = int(args.dev.split(':')[1])
125*387f9dfdSAndroid Build Coastguard Workerexcept Exception:
126*387f9dfdSAndroid Build Coastguard Worker    if '/' in args.dev:
127*387f9dfdSAndroid Build Coastguard Worker        stat = os.stat(args.dev)
128*387f9dfdSAndroid Build Coastguard Worker    else:
129*387f9dfdSAndroid Build Coastguard Worker        stat = os.stat('/dev/' + args.dev)
130*387f9dfdSAndroid Build Coastguard Worker
131*387f9dfdSAndroid Build Coastguard Worker    major = os.major(stat.st_rdev)
132*387f9dfdSAndroid Build Coastguard Worker    minor = os.minor(stat.st_rdev)
133*387f9dfdSAndroid Build Coastguard Worker
134*387f9dfdSAndroid Build Coastguard Workerif args.which == 'from-rq-alloc':
135*387f9dfdSAndroid Build Coastguard Worker    start_time_field = 'alloc_time_ns'
136*387f9dfdSAndroid Build Coastguard Workerelif args.which == 'after-rq-alloc':
137*387f9dfdSAndroid Build Coastguard Worker    start_time_field = 'start_time_ns'
138*387f9dfdSAndroid Build Coastguard Workerelif args.which == 'on-device':
139*387f9dfdSAndroid Build Coastguard Worker    start_time_field = 'io_start_time_ns'
140*387f9dfdSAndroid Build Coastguard Workerelse:
141*387f9dfdSAndroid Build Coastguard Worker    print("Invalid latency measurement {}".format(args.which))
142*387f9dfdSAndroid Build Coastguard Worker    exit()
143*387f9dfdSAndroid Build Coastguard Worker
144*387f9dfdSAndroid Build Coastguard Workerbpf_source = bpf_source.replace('__START_TIME_FIELD__', start_time_field)
145*387f9dfdSAndroid Build Coastguard Workerbpf_source = bpf_source.replace('__MAJOR__', str(major))
146*387f9dfdSAndroid Build Coastguard Workerbpf_source = bpf_source.replace('__MINOR__', str(minor))
147*387f9dfdSAndroid Build Coastguard Worker
148*387f9dfdSAndroid Build Coastguard Workerif BPF.kernel_struct_has_field(b'request', b'rq_disk') == 1:
149*387f9dfdSAndroid Build Coastguard Worker    bpf_source = bpf_source.replace('__RQ_DISK__', 'rq_disk')
150*387f9dfdSAndroid Build Coastguard Workerelse:
151*387f9dfdSAndroid Build Coastguard Worker    bpf_source = bpf_source.replace('__RQ_DISK__', 'q->disk')
152*387f9dfdSAndroid Build Coastguard Worker
153*387f9dfdSAndroid Build Coastguard Workerbpf = BPF(text=bpf_source)
154*387f9dfdSAndroid Build Coastguard Worker
155*387f9dfdSAndroid Build Coastguard Worker# times are in usecs
156*387f9dfdSAndroid Build Coastguard WorkerMSEC = 1000
157*387f9dfdSAndroid Build Coastguard WorkerSEC = 1000 * 1000
158*387f9dfdSAndroid Build Coastguard Worker
159*387f9dfdSAndroid Build Coastguard Workercur_rwdf_100ms = bpf["rwdf_100ms"]
160*387f9dfdSAndroid Build Coastguard Workercur_rwdf_1ms = bpf["rwdf_1ms"]
161*387f9dfdSAndroid Build Coastguard Workercur_rwdf_10us = bpf["rwdf_10us"]
162*387f9dfdSAndroid Build Coastguard Worker
163*387f9dfdSAndroid Build Coastguard Workerlast_rwdf_100ms = [0] * 400
164*387f9dfdSAndroid Build Coastguard Workerlast_rwdf_1ms = [0] * 400
165*387f9dfdSAndroid Build Coastguard Workerlast_rwdf_10us = [0] * 400
166*387f9dfdSAndroid Build Coastguard Worker
167*387f9dfdSAndroid Build Coastguard Workerrwdf_100ms = [0] * 400
168*387f9dfdSAndroid Build Coastguard Workerrwdf_1ms = [0] * 400
169*387f9dfdSAndroid Build Coastguard Workerrwdf_10us = [0] * 400
170*387f9dfdSAndroid Build Coastguard Worker
171*387f9dfdSAndroid Build Coastguard Workerio_type = ["read", "write", "discard", "flush"]
172*387f9dfdSAndroid Build Coastguard Worker
173*387f9dfdSAndroid Build Coastguard Workerdef find_pct(req, total, slots, idx, counted):
174*387f9dfdSAndroid Build Coastguard Worker    while idx > 0:
175*387f9dfdSAndroid Build Coastguard Worker        idx -= 1
176*387f9dfdSAndroid Build Coastguard Worker        if slots[idx] > 0:
177*387f9dfdSAndroid Build Coastguard Worker            counted += slots[idx]
178*387f9dfdSAndroid Build Coastguard Worker            if args.verbose > 1:
179*387f9dfdSAndroid Build Coastguard Worker                print('idx={} counted={} pct={:.1f} req={}'
180*387f9dfdSAndroid Build Coastguard Worker                      .format(idx, counted, counted / total, req))
181*387f9dfdSAndroid Build Coastguard Worker            if (counted / total) * 100 >= 100 - req:
182*387f9dfdSAndroid Build Coastguard Worker                break
183*387f9dfdSAndroid Build Coastguard Worker    return (idx, counted)
184*387f9dfdSAndroid Build Coastguard Worker
185*387f9dfdSAndroid Build Coastguard Workerdef calc_lat_pct(req_pcts, total, lat_100ms, lat_1ms, lat_10us):
186*387f9dfdSAndroid Build Coastguard Worker    pcts = [0] * len(req_pcts)
187*387f9dfdSAndroid Build Coastguard Worker
188*387f9dfdSAndroid Build Coastguard Worker    if total == 0:
189*387f9dfdSAndroid Build Coastguard Worker        return pcts
190*387f9dfdSAndroid Build Coastguard Worker
191*387f9dfdSAndroid Build Coastguard Worker    data = [(100 * MSEC, lat_100ms), (MSEC, lat_1ms), (10, lat_10us)]
192*387f9dfdSAndroid Build Coastguard Worker    data_sel = 0
193*387f9dfdSAndroid Build Coastguard Worker    idx = 100
194*387f9dfdSAndroid Build Coastguard Worker    counted = 0
195*387f9dfdSAndroid Build Coastguard Worker
196*387f9dfdSAndroid Build Coastguard Worker    for pct_idx in reversed(range(len(req_pcts))):
197*387f9dfdSAndroid Build Coastguard Worker        req = float(req_pcts[pct_idx])
198*387f9dfdSAndroid Build Coastguard Worker        while True:
199*387f9dfdSAndroid Build Coastguard Worker            last_counted = counted
200*387f9dfdSAndroid Build Coastguard Worker            (gran, slots) = data[data_sel]
201*387f9dfdSAndroid Build Coastguard Worker            (idx, counted) = find_pct(req, total, slots, idx, counted)
202*387f9dfdSAndroid Build Coastguard Worker            if args.verbose > 1:
203*387f9dfdSAndroid Build Coastguard Worker                print('pct_idx={} req={} gran={} idx={} counted={} total={}'
204*387f9dfdSAndroid Build Coastguard Worker                      .format(pct_idx, req, gran, idx, counted, total))
205*387f9dfdSAndroid Build Coastguard Worker            if idx > 0 or data_sel == len(data) - 1:
206*387f9dfdSAndroid Build Coastguard Worker                break
207*387f9dfdSAndroid Build Coastguard Worker            counted = last_counted
208*387f9dfdSAndroid Build Coastguard Worker            data_sel += 1
209*387f9dfdSAndroid Build Coastguard Worker            idx = 100
210*387f9dfdSAndroid Build Coastguard Worker
211*387f9dfdSAndroid Build Coastguard Worker        pcts[pct_idx] = gran * idx + gran / 2
212*387f9dfdSAndroid Build Coastguard Worker
213*387f9dfdSAndroid Build Coastguard Worker    return pcts
214*387f9dfdSAndroid Build Coastguard Worker
215*387f9dfdSAndroid Build Coastguard Workerdef format_usec(lat):
216*387f9dfdSAndroid Build Coastguard Worker    if lat > SEC:
217*387f9dfdSAndroid Build Coastguard Worker        return '{:.1f}s'.format(lat / SEC)
218*387f9dfdSAndroid Build Coastguard Worker    elif lat > 10 * MSEC:
219*387f9dfdSAndroid Build Coastguard Worker        return '{:.0f}ms'.format(lat / MSEC)
220*387f9dfdSAndroid Build Coastguard Worker    elif lat > MSEC:
221*387f9dfdSAndroid Build Coastguard Worker        return '{:.1f}ms'.format(lat / MSEC)
222*387f9dfdSAndroid Build Coastguard Worker    elif lat > 0:
223*387f9dfdSAndroid Build Coastguard Worker        return '{:.0f}us'.format(lat)
224*387f9dfdSAndroid Build Coastguard Worker    else:
225*387f9dfdSAndroid Build Coastguard Worker        return '-'
226*387f9dfdSAndroid Build Coastguard Worker
227*387f9dfdSAndroid Build Coastguard Worker# 0 interval can be used to test whether this script would run successfully.
228*387f9dfdSAndroid Build Coastguard Workerif args.interval == 0:
229*387f9dfdSAndroid Build Coastguard Worker    sys.exit(0)
230*387f9dfdSAndroid Build Coastguard Worker
231*387f9dfdSAndroid Build Coastguard Worker# Set up signal handling so that we print the result on USR1/2 and before
232*387f9dfdSAndroid Build Coastguard Worker# exiting on a signal. Combined with infinite interval, this can be used to
233*387f9dfdSAndroid Build Coastguard Worker# obtain overall latency distribution between two events. On USR2 the
234*387f9dfdSAndroid Build Coastguard Worker# accumulated counters are cleared too, which can be used to define
235*387f9dfdSAndroid Build Coastguard Worker# arbitrary intervals.
236*387f9dfdSAndroid Build Coastguard Workerforce_update_last_rwdf = False
237*387f9dfdSAndroid Build Coastguard Workerkeep_running = True
238*387f9dfdSAndroid Build Coastguard Workerresult_req = Event()
239*387f9dfdSAndroid Build Coastguard Workerdef sig_handler(sig, frame):
240*387f9dfdSAndroid Build Coastguard Worker    global keep_running, force_update_last_rwdf, result_req
241*387f9dfdSAndroid Build Coastguard Worker    if sig == signal.SIGUSR1:
242*387f9dfdSAndroid Build Coastguard Worker        force_update_last_rwdf = True
243*387f9dfdSAndroid Build Coastguard Worker    elif sig != signal.SIGUSR2:
244*387f9dfdSAndroid Build Coastguard Worker        keep_running = False
245*387f9dfdSAndroid Build Coastguard Worker    result_req.set()
246*387f9dfdSAndroid Build Coastguard Worker
247*387f9dfdSAndroid Build Coastguard Workerfor sig in (signal.SIGUSR1, signal.SIGUSR2, signal.SIGINT, signal.SIGTERM, signal.SIGHUP):
248*387f9dfdSAndroid Build Coastguard Worker    signal.signal(sig, sig_handler)
249*387f9dfdSAndroid Build Coastguard Worker
250*387f9dfdSAndroid Build Coastguard Worker# If infinite interval, always trigger the first output so that the caller
251*387f9dfdSAndroid Build Coastguard Worker# can tell when initialization is complete.
252*387f9dfdSAndroid Build Coastguard Workerif args.interval < 0:
253*387f9dfdSAndroid Build Coastguard Worker    result_req.set();
254*387f9dfdSAndroid Build Coastguard Worker
255*387f9dfdSAndroid Build Coastguard Workerwhile keep_running:
256*387f9dfdSAndroid Build Coastguard Worker    result_req.wait(args.interval if args.interval > 0 else None)
257*387f9dfdSAndroid Build Coastguard Worker    result_req.clear()
258*387f9dfdSAndroid Build Coastguard Worker
259*387f9dfdSAndroid Build Coastguard Worker    update_last_rwdf = args.interval > 0 or force_update_last_rwdf
260*387f9dfdSAndroid Build Coastguard Worker    force_update_last_rwdf = False
261*387f9dfdSAndroid Build Coastguard Worker    rwdf_total = [0] * 4;
262*387f9dfdSAndroid Build Coastguard Worker
263*387f9dfdSAndroid Build Coastguard Worker    for i in range(400):
264*387f9dfdSAndroid Build Coastguard Worker        v = cur_rwdf_100ms.sum(i).value
265*387f9dfdSAndroid Build Coastguard Worker        rwdf_100ms[i] = max(v - last_rwdf_100ms[i], 0)
266*387f9dfdSAndroid Build Coastguard Worker        if update_last_rwdf:
267*387f9dfdSAndroid Build Coastguard Worker            last_rwdf_100ms[i] = v
268*387f9dfdSAndroid Build Coastguard Worker
269*387f9dfdSAndroid Build Coastguard Worker        v = cur_rwdf_1ms.sum(i).value
270*387f9dfdSAndroid Build Coastguard Worker        rwdf_1ms[i] = max(v - last_rwdf_1ms[i], 0)
271*387f9dfdSAndroid Build Coastguard Worker        if update_last_rwdf:
272*387f9dfdSAndroid Build Coastguard Worker            last_rwdf_1ms[i] = v
273*387f9dfdSAndroid Build Coastguard Worker
274*387f9dfdSAndroid Build Coastguard Worker        v = cur_rwdf_10us.sum(i).value
275*387f9dfdSAndroid Build Coastguard Worker        rwdf_10us[i] = max(v - last_rwdf_10us[i], 0)
276*387f9dfdSAndroid Build Coastguard Worker        if update_last_rwdf:
277*387f9dfdSAndroid Build Coastguard Worker            last_rwdf_10us[i] = v
278*387f9dfdSAndroid Build Coastguard Worker
279*387f9dfdSAndroid Build Coastguard Worker        rwdf_total[int(i / 100)] += rwdf_100ms[i]
280*387f9dfdSAndroid Build Coastguard Worker
281*387f9dfdSAndroid Build Coastguard Worker    rwdf_lat = []
282*387f9dfdSAndroid Build Coastguard Worker    for i in range(4):
283*387f9dfdSAndroid Build Coastguard Worker        left = i * 100
284*387f9dfdSAndroid Build Coastguard Worker        right = left + 100
285*387f9dfdSAndroid Build Coastguard Worker        rwdf_lat.append(
286*387f9dfdSAndroid Build Coastguard Worker            calc_lat_pct(args.pcts, rwdf_total[i],
287*387f9dfdSAndroid Build Coastguard Worker                         rwdf_100ms[left:right],
288*387f9dfdSAndroid Build Coastguard Worker                         rwdf_1ms[left:right],
289*387f9dfdSAndroid Build Coastguard Worker                         rwdf_10us[left:right]))
290*387f9dfdSAndroid Build Coastguard Worker
291*387f9dfdSAndroid Build Coastguard Worker        if args.verbose:
292*387f9dfdSAndroid Build Coastguard Worker            print('{:7} 100ms {}'.format(io_type[i], rwdf_100ms[left:right]))
293*387f9dfdSAndroid Build Coastguard Worker            print('{:7}   1ms {}'.format(io_type[i], rwdf_1ms[left:right]))
294*387f9dfdSAndroid Build Coastguard Worker            print('{:7}  10us {}'.format(io_type[i], rwdf_10us[left:right]))
295*387f9dfdSAndroid Build Coastguard Worker
296*387f9dfdSAndroid Build Coastguard Worker    if args.json:
297*387f9dfdSAndroid Build Coastguard Worker        result = {}
298*387f9dfdSAndroid Build Coastguard Worker        for iot in range(4):
299*387f9dfdSAndroid Build Coastguard Worker            lats = {}
300*387f9dfdSAndroid Build Coastguard Worker            for pi in range(len(args.pcts)):
301*387f9dfdSAndroid Build Coastguard Worker                lats[args.pcts[pi]] = rwdf_lat[iot][pi] / SEC
302*387f9dfdSAndroid Build Coastguard Worker            result[io_type[iot]] = lats
303*387f9dfdSAndroid Build Coastguard Worker        print(json.dumps(result), flush=True)
304*387f9dfdSAndroid Build Coastguard Worker    else:
305*387f9dfdSAndroid Build Coastguard Worker        print('\n{:<7}'.format(os.path.basename(args.dev)), end='')
306*387f9dfdSAndroid Build Coastguard Worker        widths = []
307*387f9dfdSAndroid Build Coastguard Worker        for pct in args.pcts:
308*387f9dfdSAndroid Build Coastguard Worker            widths.append(max(len(pct), 5))
309*387f9dfdSAndroid Build Coastguard Worker            print(' {:>5}'.format(pct), end='')
310*387f9dfdSAndroid Build Coastguard Worker        print()
311*387f9dfdSAndroid Build Coastguard Worker        for iot in range(4):
312*387f9dfdSAndroid Build Coastguard Worker            print('{:7}'.format(io_type[iot]), end='')
313*387f9dfdSAndroid Build Coastguard Worker            for pi in range(len(rwdf_lat[iot])):
314*387f9dfdSAndroid Build Coastguard Worker                print(' {:>{}}'.format(format_usec(rwdf_lat[iot][pi]), widths[pi]), end='')
315*387f9dfdSAndroid Build Coastguard Worker            print()
316