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