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