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# cachetop Count cache kernel function calls per processes 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: cachetop 8*387f9dfdSAndroid Build Coastguard Worker# Taken from cachestat by Brendan Gregg 9*387f9dfdSAndroid Build Coastguard Worker# 10*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2016-present, Facebook, Inc. 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# 13-Jul-2016 Emmanuel Bretelle first version 14*387f9dfdSAndroid Build Coastguard Worker# 17-Mar-2022 Rocky Xing Added PID filter support. 15*387f9dfdSAndroid Build Coastguard Worker# 15-Feb-2023 Rong Tao Add writeback_dirty_{folio,page} tracepoints 16*387f9dfdSAndroid Build Coastguard Worker 17*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import absolute_import 18*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import division 19*387f9dfdSAndroid Build Coastguard Worker# Do not import unicode_literals until #623 is fixed 20*387f9dfdSAndroid Build Coastguard Worker# from __future__ import unicode_literals 21*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 22*387f9dfdSAndroid Build Coastguard Worker 23*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 24*387f9dfdSAndroid Build Coastguard Workerfrom collections import defaultdict 25*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime 26*387f9dfdSAndroid Build Coastguard Worker 27*387f9dfdSAndroid Build Coastguard Workerimport argparse 28*387f9dfdSAndroid Build Coastguard Workerimport curses 29*387f9dfdSAndroid Build Coastguard Workerimport pwd 30*387f9dfdSAndroid Build Coastguard Workerimport re 31*387f9dfdSAndroid Build Coastguard Workerimport signal 32*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep 33*387f9dfdSAndroid Build Coastguard Worker 34*387f9dfdSAndroid Build Coastguard WorkerFIELDS = ( 35*387f9dfdSAndroid Build Coastguard Worker "PID", 36*387f9dfdSAndroid Build Coastguard Worker "UID", 37*387f9dfdSAndroid Build Coastguard Worker "CMD", 38*387f9dfdSAndroid Build Coastguard Worker "HITS", 39*387f9dfdSAndroid Build Coastguard Worker "MISSES", 40*387f9dfdSAndroid Build Coastguard Worker "DIRTIES", 41*387f9dfdSAndroid Build Coastguard Worker "READ_HIT%", 42*387f9dfdSAndroid Build Coastguard Worker "WRITE_HIT%" 43*387f9dfdSAndroid Build Coastguard Worker) 44*387f9dfdSAndroid Build Coastguard WorkerDEFAULT_FIELD = "HITS" 45*387f9dfdSAndroid Build Coastguard WorkerDEFAULT_SORT_FIELD = FIELDS.index(DEFAULT_FIELD) 46*387f9dfdSAndroid Build Coastguard Worker 47*387f9dfdSAndroid Build Coastguard Worker# signal handler 48*387f9dfdSAndroid Build Coastguard Workerdef signal_ignore(signal, frame): 49*387f9dfdSAndroid Build Coastguard Worker print() 50*387f9dfdSAndroid Build Coastguard Worker 51*387f9dfdSAndroid Build Coastguard Worker 52*387f9dfdSAndroid Build Coastguard Worker# Function to gather data from /proc/meminfo 53*387f9dfdSAndroid Build Coastguard Worker# return dictionary for quicker lookup of both values 54*387f9dfdSAndroid Build Coastguard Workerdef get_meminfo(): 55*387f9dfdSAndroid Build Coastguard Worker result = {} 56*387f9dfdSAndroid Build Coastguard Worker 57*387f9dfdSAndroid Build Coastguard Worker for line in open('/proc/meminfo'): 58*387f9dfdSAndroid Build Coastguard Worker k = line.split(':', 3) 59*387f9dfdSAndroid Build Coastguard Worker v = k[1].split() 60*387f9dfdSAndroid Build Coastguard Worker result[k[0]] = int(v[0]) 61*387f9dfdSAndroid Build Coastguard Worker return result 62*387f9dfdSAndroid Build Coastguard Worker 63*387f9dfdSAndroid Build Coastguard Worker 64*387f9dfdSAndroid Build Coastguard Workerdef get_processes_stats( 65*387f9dfdSAndroid Build Coastguard Worker bpf, 66*387f9dfdSAndroid Build Coastguard Worker sort_field=DEFAULT_SORT_FIELD, 67*387f9dfdSAndroid Build Coastguard Worker sort_reverse=False): 68*387f9dfdSAndroid Build Coastguard Worker ''' 69*387f9dfdSAndroid Build Coastguard Worker Return a tuple containing: 70*387f9dfdSAndroid Build Coastguard Worker buffer 71*387f9dfdSAndroid Build Coastguard Worker cached 72*387f9dfdSAndroid Build Coastguard Worker list of tuple with per process cache stats 73*387f9dfdSAndroid Build Coastguard Worker ''' 74*387f9dfdSAndroid Build Coastguard Worker counts = bpf.get_table("counts") 75*387f9dfdSAndroid Build Coastguard Worker stats = defaultdict(lambda: defaultdict(int)) 76*387f9dfdSAndroid Build Coastguard Worker for k, v in counts.items(): 77*387f9dfdSAndroid Build Coastguard Worker stats["%d-%d-%s" % (k.pid, k.uid, k.comm.decode('utf-8', 'replace'))][k.nf] = v.value 78*387f9dfdSAndroid Build Coastguard Worker stats_list = [] 79*387f9dfdSAndroid Build Coastguard Worker 80*387f9dfdSAndroid Build Coastguard Worker for pid, count in sorted(stats.items(), key=lambda stat: stat[0]): 81*387f9dfdSAndroid Build Coastguard Worker rtaccess = 0 82*387f9dfdSAndroid Build Coastguard Worker wtaccess = 0 83*387f9dfdSAndroid Build Coastguard Worker mpa = 0 84*387f9dfdSAndroid Build Coastguard Worker mbd = 0 85*387f9dfdSAndroid Build Coastguard Worker apcl = 0 86*387f9dfdSAndroid Build Coastguard Worker apd = 0 87*387f9dfdSAndroid Build Coastguard Worker access = 0 88*387f9dfdSAndroid Build Coastguard Worker misses = 0 89*387f9dfdSAndroid Build Coastguard Worker rhits = 0 90*387f9dfdSAndroid Build Coastguard Worker whits = 0 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker for k, v in count.items(): 93*387f9dfdSAndroid Build Coastguard Worker if k == 0: # NF_APCL 94*387f9dfdSAndroid Build Coastguard Worker apcl = max(0, v) 95*387f9dfdSAndroid Build Coastguard Worker 96*387f9dfdSAndroid Build Coastguard Worker if k == 1: # NF_MPA 97*387f9dfdSAndroid Build Coastguard Worker mpa = max(0, v) 98*387f9dfdSAndroid Build Coastguard Worker 99*387f9dfdSAndroid Build Coastguard Worker if k == 2: # NF_MBD 100*387f9dfdSAndroid Build Coastguard Worker mbd = max(0, v) 101*387f9dfdSAndroid Build Coastguard Worker 102*387f9dfdSAndroid Build Coastguard Worker if k == 3: # NF_APD 103*387f9dfdSAndroid Build Coastguard Worker apd = max(0, v) 104*387f9dfdSAndroid Build Coastguard Worker 105*387f9dfdSAndroid Build Coastguard Worker # access = total cache access incl. reads(mpa) and writes(mbd) 106*387f9dfdSAndroid Build Coastguard Worker # misses = total of add to lru which we do when we write(mbd) 107*387f9dfdSAndroid Build Coastguard Worker # and also the mark the page dirty(same as mbd) 108*387f9dfdSAndroid Build Coastguard Worker access = (mpa + mbd) 109*387f9dfdSAndroid Build Coastguard Worker misses = (apcl + apd) 110*387f9dfdSAndroid Build Coastguard Worker 111*387f9dfdSAndroid Build Coastguard Worker # rtaccess is the read hit % during the sample period. 112*387f9dfdSAndroid Build Coastguard Worker # wtaccess is the write hit % during the sample period. 113*387f9dfdSAndroid Build Coastguard Worker if mpa > 0: 114*387f9dfdSAndroid Build Coastguard Worker rtaccess = float(mpa) / (access + misses) 115*387f9dfdSAndroid Build Coastguard Worker if apcl > 0: 116*387f9dfdSAndroid Build Coastguard Worker wtaccess = float(apcl) / (access + misses) 117*387f9dfdSAndroid Build Coastguard Worker 118*387f9dfdSAndroid Build Coastguard Worker if wtaccess != 0: 119*387f9dfdSAndroid Build Coastguard Worker whits = 100 * wtaccess 120*387f9dfdSAndroid Build Coastguard Worker if rtaccess != 0: 121*387f9dfdSAndroid Build Coastguard Worker rhits = 100 * rtaccess 122*387f9dfdSAndroid Build Coastguard Worker 123*387f9dfdSAndroid Build Coastguard Worker _pid, uid, comm = pid.split('-', 2) 124*387f9dfdSAndroid Build Coastguard Worker stats_list.append( 125*387f9dfdSAndroid Build Coastguard Worker (int(_pid), uid, comm, 126*387f9dfdSAndroid Build Coastguard Worker access, misses, mbd, 127*387f9dfdSAndroid Build Coastguard Worker rhits, whits)) 128*387f9dfdSAndroid Build Coastguard Worker 129*387f9dfdSAndroid Build Coastguard Worker stats_list = sorted( 130*387f9dfdSAndroid Build Coastguard Worker stats_list, key=lambda stat: stat[sort_field], reverse=sort_reverse 131*387f9dfdSAndroid Build Coastguard Worker ) 132*387f9dfdSAndroid Build Coastguard Worker counts.clear() 133*387f9dfdSAndroid Build Coastguard Worker return stats_list 134*387f9dfdSAndroid Build Coastguard Worker 135*387f9dfdSAndroid Build Coastguard Worker 136*387f9dfdSAndroid Build Coastguard Workerdef handle_loop(stdscr, args): 137*387f9dfdSAndroid Build Coastguard Worker # don't wait on key press 138*387f9dfdSAndroid Build Coastguard Worker stdscr.nodelay(1) 139*387f9dfdSAndroid Build Coastguard Worker # set default sorting field 140*387f9dfdSAndroid Build Coastguard Worker sort_field = FIELDS.index(DEFAULT_FIELD) 141*387f9dfdSAndroid Build Coastguard Worker sort_reverse = True 142*387f9dfdSAndroid Build Coastguard Worker 143*387f9dfdSAndroid Build Coastguard Worker # load BPF program 144*387f9dfdSAndroid Build Coastguard Worker bpf_text = """ 145*387f9dfdSAndroid Build Coastguard Worker 146*387f9dfdSAndroid Build Coastguard Worker #include <uapi/linux/ptrace.h> 147*387f9dfdSAndroid Build Coastguard Worker struct key_t { 148*387f9dfdSAndroid Build Coastguard Worker // NF_{APCL,MPA,MBD,APD} 149*387f9dfdSAndroid Build Coastguard Worker u64 nf; 150*387f9dfdSAndroid Build Coastguard Worker u32 pid; 151*387f9dfdSAndroid Build Coastguard Worker u32 uid; 152*387f9dfdSAndroid Build Coastguard Worker char comm[16]; 153*387f9dfdSAndroid Build Coastguard Worker }; 154*387f9dfdSAndroid Build Coastguard Worker enum { 155*387f9dfdSAndroid Build Coastguard Worker NF_APCL, 156*387f9dfdSAndroid Build Coastguard Worker NF_MPA, 157*387f9dfdSAndroid Build Coastguard Worker NF_MBD, 158*387f9dfdSAndroid Build Coastguard Worker NF_APD, 159*387f9dfdSAndroid Build Coastguard Worker }; 160*387f9dfdSAndroid Build Coastguard Worker 161*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(counts, struct key_t); 162*387f9dfdSAndroid Build Coastguard Worker 163*387f9dfdSAndroid Build Coastguard Worker static int __do_count(void *ctx, u64 nf) { 164*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid() >> 32; 165*387f9dfdSAndroid Build Coastguard Worker if (FILTER_PID) 166*387f9dfdSAndroid Build Coastguard Worker return 0; 167*387f9dfdSAndroid Build Coastguard Worker 168*387f9dfdSAndroid Build Coastguard Worker struct key_t key = {}; 169*387f9dfdSAndroid Build Coastguard Worker u32 uid = bpf_get_current_uid_gid(); 170*387f9dfdSAndroid Build Coastguard Worker 171*387f9dfdSAndroid Build Coastguard Worker key.nf = nf; 172*387f9dfdSAndroid Build Coastguard Worker key.pid = pid; 173*387f9dfdSAndroid Build Coastguard Worker key.uid = uid; 174*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&(key.comm), 16); 175*387f9dfdSAndroid Build Coastguard Worker 176*387f9dfdSAndroid Build Coastguard Worker counts.increment(key); 177*387f9dfdSAndroid Build Coastguard Worker return 0; 178*387f9dfdSAndroid Build Coastguard Worker } 179*387f9dfdSAndroid Build Coastguard Worker int do_count_apcl(struct pt_regs *ctx) { 180*387f9dfdSAndroid Build Coastguard Worker return __do_count(ctx, NF_APCL); 181*387f9dfdSAndroid Build Coastguard Worker } 182*387f9dfdSAndroid Build Coastguard Worker int do_count_mpa(struct pt_regs *ctx) { 183*387f9dfdSAndroid Build Coastguard Worker return __do_count(ctx, NF_MPA); 184*387f9dfdSAndroid Build Coastguard Worker } 185*387f9dfdSAndroid Build Coastguard Worker int do_count_mbd(struct pt_regs *ctx) { 186*387f9dfdSAndroid Build Coastguard Worker return __do_count(ctx, NF_MBD); 187*387f9dfdSAndroid Build Coastguard Worker } 188*387f9dfdSAndroid Build Coastguard Worker int do_count_apd(struct pt_regs *ctx) { 189*387f9dfdSAndroid Build Coastguard Worker return __do_count(ctx, NF_APD); 190*387f9dfdSAndroid Build Coastguard Worker } 191*387f9dfdSAndroid Build Coastguard Worker int do_count_apd_tp(void *ctx) { 192*387f9dfdSAndroid Build Coastguard Worker return __do_count(ctx, NF_APD); 193*387f9dfdSAndroid Build Coastguard Worker } 194*387f9dfdSAndroid Build Coastguard Worker 195*387f9dfdSAndroid Build Coastguard Worker """ 196*387f9dfdSAndroid Build Coastguard Worker 197*387f9dfdSAndroid Build Coastguard Worker if args.pid: 198*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_PID', 'pid != %d' % args.pid) 199*387f9dfdSAndroid Build Coastguard Worker else: 200*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_PID', '0') 201*387f9dfdSAndroid Build Coastguard Worker 202*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=bpf_text) 203*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event="add_to_page_cache_lru", fn_name="do_count_apcl") 204*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event="mark_page_accessed", fn_name="do_count_mpa") 205*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event="mark_buffer_dirty", fn_name="do_count_mbd") 206*387f9dfdSAndroid Build Coastguard Worker 207*387f9dfdSAndroid Build Coastguard Worker # Function account_page_dirtied() is changed to folio_account_dirtied() in 5.15. 208*387f9dfdSAndroid Build Coastguard Worker # Introduce tracepoint writeback_dirty_{page,folio} 209*387f9dfdSAndroid Build Coastguard Worker if BPF.get_kprobe_functions(b'folio_account_dirtied'): 210*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event="folio_account_dirtied", fn_name="do_count_apd") 211*387f9dfdSAndroid Build Coastguard Worker elif BPF.get_kprobe_functions(b'account_page_dirtied'): 212*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event="account_page_dirtied", fn_name="do_count_apd") 213*387f9dfdSAndroid Build Coastguard Worker elif BPF.tracepoint_exists("writeback", "writeback_dirty_folio"): 214*387f9dfdSAndroid Build Coastguard Worker b.attach_tracepoint(tp="writeback:writeback_dirty_folio", fn_name="do_count_apd_tp") 215*387f9dfdSAndroid Build Coastguard Worker elif BPF.tracepoint_exists("writeback", "writeback_dirty_page"): 216*387f9dfdSAndroid Build Coastguard Worker b.attach_tracepoint(tp="writeback:writeback_dirty_page", fn_name="do_count_apd_tp") 217*387f9dfdSAndroid Build Coastguard Worker else: 218*387f9dfdSAndroid Build Coastguard Worker raise Exception("Failed to attach kprobe %s or %s and any tracepoint" % 219*387f9dfdSAndroid Build Coastguard Worker ("folio_account_dirtied", "account_page_dirtied")) 220*387f9dfdSAndroid Build Coastguard Worker 221*387f9dfdSAndroid Build Coastguard Worker exiting = 0 222*387f9dfdSAndroid Build Coastguard Worker 223*387f9dfdSAndroid Build Coastguard Worker while 1: 224*387f9dfdSAndroid Build Coastguard Worker s = stdscr.getch() 225*387f9dfdSAndroid Build Coastguard Worker if s == ord('q'): 226*387f9dfdSAndroid Build Coastguard Worker exiting = 1 227*387f9dfdSAndroid Build Coastguard Worker elif s == ord('r'): 228*387f9dfdSAndroid Build Coastguard Worker sort_reverse = not sort_reverse 229*387f9dfdSAndroid Build Coastguard Worker elif s == ord('<'): 230*387f9dfdSAndroid Build Coastguard Worker sort_field = max(0, sort_field - 1) 231*387f9dfdSAndroid Build Coastguard Worker elif s == ord('>'): 232*387f9dfdSAndroid Build Coastguard Worker sort_field = min(len(FIELDS) - 1, sort_field + 1) 233*387f9dfdSAndroid Build Coastguard Worker try: 234*387f9dfdSAndroid Build Coastguard Worker sleep(args.interval) 235*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 236*387f9dfdSAndroid Build Coastguard Worker exiting = 1 237*387f9dfdSAndroid Build Coastguard Worker # as cleanup can take many seconds, trap Ctrl-C: 238*387f9dfdSAndroid Build Coastguard Worker signal.signal(signal.SIGINT, signal_ignore) 239*387f9dfdSAndroid Build Coastguard Worker 240*387f9dfdSAndroid Build Coastguard Worker # Get memory info 241*387f9dfdSAndroid Build Coastguard Worker mem = get_meminfo() 242*387f9dfdSAndroid Build Coastguard Worker cached = int(mem["Cached"]) / 1024 243*387f9dfdSAndroid Build Coastguard Worker buff = int(mem["Buffers"]) / 1024 244*387f9dfdSAndroid Build Coastguard Worker 245*387f9dfdSAndroid Build Coastguard Worker process_stats = get_processes_stats( 246*387f9dfdSAndroid Build Coastguard Worker b, 247*387f9dfdSAndroid Build Coastguard Worker sort_field=sort_field, 248*387f9dfdSAndroid Build Coastguard Worker sort_reverse=sort_reverse) 249*387f9dfdSAndroid Build Coastguard Worker stdscr.clear() 250*387f9dfdSAndroid Build Coastguard Worker stdscr.addstr( 251*387f9dfdSAndroid Build Coastguard Worker 0, 0, 252*387f9dfdSAndroid Build Coastguard Worker "%-8s Buffers MB: %.0f / Cached MB: %.0f " 253*387f9dfdSAndroid Build Coastguard Worker "/ Sort: %s / Order: %s" % ( 254*387f9dfdSAndroid Build Coastguard Worker strftime("%H:%M:%S"), buff, cached, FIELDS[sort_field], 255*387f9dfdSAndroid Build Coastguard Worker sort_reverse and "descending" or "ascending" 256*387f9dfdSAndroid Build Coastguard Worker ) 257*387f9dfdSAndroid Build Coastguard Worker ) 258*387f9dfdSAndroid Build Coastguard Worker 259*387f9dfdSAndroid Build Coastguard Worker # header 260*387f9dfdSAndroid Build Coastguard Worker stdscr.addstr( 261*387f9dfdSAndroid Build Coastguard Worker 1, 0, 262*387f9dfdSAndroid Build Coastguard Worker "{0:8} {1:8} {2:16} {3:8} {4:8} {5:8} {6:10} {7:10}".format( 263*387f9dfdSAndroid Build Coastguard Worker *FIELDS 264*387f9dfdSAndroid Build Coastguard Worker ), 265*387f9dfdSAndroid Build Coastguard Worker curses.A_REVERSE 266*387f9dfdSAndroid Build Coastguard Worker ) 267*387f9dfdSAndroid Build Coastguard Worker (height, width) = stdscr.getmaxyx() 268*387f9dfdSAndroid Build Coastguard Worker for i, stat in enumerate(process_stats): 269*387f9dfdSAndroid Build Coastguard Worker uid = int(stat[1]) 270*387f9dfdSAndroid Build Coastguard Worker try: 271*387f9dfdSAndroid Build Coastguard Worker username = pwd.getpwuid(uid)[0] 272*387f9dfdSAndroid Build Coastguard Worker except KeyError: 273*387f9dfdSAndroid Build Coastguard Worker # `pwd` throws a KeyError if the user cannot be found. This can 274*387f9dfdSAndroid Build Coastguard Worker # happen e.g. when the process is running in a cgroup that has 275*387f9dfdSAndroid Build Coastguard Worker # different users from the host. 276*387f9dfdSAndroid Build Coastguard Worker username = 'UNKNOWN({})'.format(uid) 277*387f9dfdSAndroid Build Coastguard Worker 278*387f9dfdSAndroid Build Coastguard Worker stdscr.addstr( 279*387f9dfdSAndroid Build Coastguard Worker i + 2, 0, 280*387f9dfdSAndroid Build Coastguard Worker "{0:8} {username:8.8} {2:16} {3:8} {4:8} " 281*387f9dfdSAndroid Build Coastguard Worker "{5:8} {6:9.1f}% {7:9.1f}%".format( 282*387f9dfdSAndroid Build Coastguard Worker *stat, username=username 283*387f9dfdSAndroid Build Coastguard Worker ) 284*387f9dfdSAndroid Build Coastguard Worker ) 285*387f9dfdSAndroid Build Coastguard Worker if i > height - 4: 286*387f9dfdSAndroid Build Coastguard Worker break 287*387f9dfdSAndroid Build Coastguard Worker stdscr.refresh() 288*387f9dfdSAndroid Build Coastguard Worker if exiting: 289*387f9dfdSAndroid Build Coastguard Worker print("Detaching...") 290*387f9dfdSAndroid Build Coastguard Worker return 291*387f9dfdSAndroid Build Coastguard Worker 292*387f9dfdSAndroid Build Coastguard Worker 293*387f9dfdSAndroid Build Coastguard Workerdef parse_arguments(): 294*387f9dfdSAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 295*387f9dfdSAndroid Build Coastguard Worker description='Show Linux page cache hit/miss statistics including read ' 296*387f9dfdSAndroid Build Coastguard Worker 'and write hit % per processes in a UI like top.' 297*387f9dfdSAndroid Build Coastguard Worker ) 298*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-p", "--pid", type=int, metavar="PID", 299*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only") 300*387f9dfdSAndroid Build Coastguard Worker parser.add_argument( 301*387f9dfdSAndroid Build Coastguard Worker 'interval', type=int, default=5, nargs='?', 302*387f9dfdSAndroid Build Coastguard Worker help='Interval between probes.' 303*387f9dfdSAndroid Build Coastguard Worker ) 304*387f9dfdSAndroid Build Coastguard Worker 305*387f9dfdSAndroid Build Coastguard Worker args = parser.parse_args() 306*387f9dfdSAndroid Build Coastguard Worker return args 307*387f9dfdSAndroid Build Coastguard Worker 308*387f9dfdSAndroid Build Coastguard Workerargs = parse_arguments() 309*387f9dfdSAndroid Build Coastguard Workercurses.wrapper(handle_loop, args) 310