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# swapin Count swapins by process. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# TODO: add -s for total swapin time column (sum) 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2019 Brendan Gregg. 10*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"). 11*387f9dfdSAndroid Build Coastguard Worker# This was originally created for the BPF Performance Tools book 12*387f9dfdSAndroid Build Coastguard Worker# published by Addison Wesley. ISBN-13: 9780136554820 13*387f9dfdSAndroid Build Coastguard Worker# When copying or porting, include this comment. 14*387f9dfdSAndroid Build Coastguard Worker# 15*387f9dfdSAndroid Build Coastguard Worker# 03-Jul-2019 Brendan Gregg Ported from bpftrace to BCC. 16*387f9dfdSAndroid Build Coastguard Worker 17*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 18*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 19*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime 20*387f9dfdSAndroid Build Coastguard Workerimport argparse 21*387f9dfdSAndroid Build Coastguard Worker 22*387f9dfdSAndroid Build Coastguard Worker# arguments 23*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 24*387f9dfdSAndroid Build Coastguard Worker description="Count swapin events by process.") 25*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--notime", action="store_true", 26*387f9dfdSAndroid Build Coastguard Worker help="do not show the timestamp (HH:MM:SS)") 27*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("interval", nargs="?", default=1, 28*387f9dfdSAndroid Build Coastguard Worker help="output interval, in seconds") 29*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("count", nargs="?", default=99999999, 30*387f9dfdSAndroid Build Coastguard Worker help="number of outputs") 31*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true", 32*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 33*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 34*387f9dfdSAndroid Build Coastguard Workerinterval = int(args.interval) 35*387f9dfdSAndroid Build Coastguard Workercountdown = int(args.count) 36*387f9dfdSAndroid Build Coastguard Workerdebug = 0 37*387f9dfdSAndroid Build Coastguard Worker 38*387f9dfdSAndroid Build Coastguard Worker# load BPF program 39*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=""" 40*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 41*387f9dfdSAndroid Build Coastguard Worker 42*387f9dfdSAndroid Build Coastguard Workerstruct key_t { 43*387f9dfdSAndroid Build Coastguard Worker u32 pid; 44*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 45*387f9dfdSAndroid Build Coastguard Worker}; 46*387f9dfdSAndroid Build Coastguard Worker 47*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(counts, struct key_t, u64); 48*387f9dfdSAndroid Build Coastguard Worker 49*387f9dfdSAndroid Build Coastguard Workerint kprobe__swap_readpage(struct pt_regs *ctx) 50*387f9dfdSAndroid Build Coastguard Worker{ 51*387f9dfdSAndroid Build Coastguard Worker u64 *val, zero = 0; 52*387f9dfdSAndroid Build Coastguard Worker u32 tgid = bpf_get_current_pid_tgid() >> 32; 53*387f9dfdSAndroid Build Coastguard Worker struct key_t key = {.pid = tgid}; 54*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&key.comm, sizeof(key.comm)); 55*387f9dfdSAndroid Build Coastguard Worker val = counts.lookup_or_init(&key, &zero); 56*387f9dfdSAndroid Build Coastguard Worker ++(*val); 57*387f9dfdSAndroid Build Coastguard Worker return 0; 58*387f9dfdSAndroid Build Coastguard Worker} 59*387f9dfdSAndroid Build Coastguard Worker""") 60*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf: 61*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 62*387f9dfdSAndroid Build Coastguard Worker if args.ebpf: 63*387f9dfdSAndroid Build Coastguard Worker exit() 64*387f9dfdSAndroid Build Coastguard Worker 65*387f9dfdSAndroid Build Coastguard Workerprint("Counting swap ins. Ctrl-C to end."); 66*387f9dfdSAndroid Build Coastguard Worker 67*387f9dfdSAndroid Build Coastguard Worker# output 68*387f9dfdSAndroid Build Coastguard Workerexiting = 0 69*387f9dfdSAndroid Build Coastguard Workerwhile 1: 70*387f9dfdSAndroid Build Coastguard Worker try: 71*387f9dfdSAndroid Build Coastguard Worker sleep(interval) 72*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 73*387f9dfdSAndroid Build Coastguard Worker exiting = 1 74*387f9dfdSAndroid Build Coastguard Worker 75*387f9dfdSAndroid Build Coastguard Worker if not args.notime: 76*387f9dfdSAndroid Build Coastguard Worker print(strftime("%H:%M:%S")) 77*387f9dfdSAndroid Build Coastguard Worker print("%-16s %-7s %s" % ("COMM", "PID", "COUNT")) 78*387f9dfdSAndroid Build Coastguard Worker counts = b.get_table("counts") 79*387f9dfdSAndroid Build Coastguard Worker for k, v in sorted(counts.items(), 80*387f9dfdSAndroid Build Coastguard Worker key=lambda counts: counts[1].value): 81*387f9dfdSAndroid Build Coastguard Worker print("%-16s %-7d %d" % (k.comm, k.pid, v.value)) 82*387f9dfdSAndroid Build Coastguard Worker counts.clear() 83*387f9dfdSAndroid Build Coastguard Worker print() 84*387f9dfdSAndroid Build Coastguard Worker 85*387f9dfdSAndroid Build Coastguard Worker countdown -= 1 86*387f9dfdSAndroid Build Coastguard Worker if exiting or countdown == 0: 87*387f9dfdSAndroid Build Coastguard Worker print("Detaching...") 88*387f9dfdSAndroid Build Coastguard Worker exit() 89