mcaleavya | 6959dcf | 2016-02-06 12:00:34 +0000 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # |
| 3 | # bitehist.py Block I/O size histogram. |
| 4 | # For Linux, uses BCC, eBPF. See .c file. |
| 5 | # |
| 6 | # USAGE: bitesize |
mcaleavya | 6959dcf | 2016-02-06 12:00:34 +0000 | [diff] [blame] | 7 | # |
Brendan Gregg | 6497a84 | 2016-02-06 17:08:38 -0800 | [diff] [blame] | 8 | # Ctrl-C will print the partially gathered histogram then exit. |
mcaleavya | 6959dcf | 2016-02-06 12:00:34 +0000 | [diff] [blame] | 9 | # |
| 10 | # Copyright (c) 2016 Allan McAleavy |
| 11 | # Licensed under the Apache License, Version 2.0 (the "License") |
| 12 | # |
| 13 | # 05-Feb-2016 Allan McAleavy ran pep8 against file |
| 14 | |
| 15 | from bcc import BPF |
| 16 | from time import sleep |
| 17 | |
| 18 | bpf_text = """ |
| 19 | #include <uapi/linux/ptrace.h> |
| 20 | #include <linux/blkdev.h> |
| 21 | |
Brendan Gregg | f6e92c9 | 2016-02-06 17:11:59 -0800 | [diff] [blame^] | 22 | struct proc_key_t { |
mcaleavya | 6959dcf | 2016-02-06 12:00:34 +0000 | [diff] [blame] | 23 | char name[TASK_COMM_LEN]; |
| 24 | u64 slot; |
| 25 | }; |
| 26 | |
| 27 | struct val_t { |
| 28 | char name[TASK_COMM_LEN]; |
| 29 | }; |
| 30 | |
| 31 | BPF_HISTOGRAM(dist, struct proc_key_t); |
| 32 | BPF_HASH(commbyreq, struct request *, struct val_t); |
| 33 | |
| 34 | int trace_pid_start(struct pt_regs *ctx, struct request *req) |
| 35 | { |
| 36 | struct val_t val = {}; |
| 37 | |
| 38 | if (bpf_get_current_comm(&val.name, sizeof(val.name)) == 0) { |
| 39 | commbyreq.update(&req, &val); |
| 40 | } |
| 41 | return 0; |
| 42 | } |
| 43 | |
Brendan Gregg | f6e92c9 | 2016-02-06 17:11:59 -0800 | [diff] [blame^] | 44 | int do_count(struct pt_regs *ctx, struct request *req) |
mcaleavya | 6959dcf | 2016-02-06 12:00:34 +0000 | [diff] [blame] | 45 | { |
| 46 | struct val_t *valp; |
| 47 | |
| 48 | valp = commbyreq.lookup(&req); |
Brendan Gregg | f6e92c9 | 2016-02-06 17:11:59 -0800 | [diff] [blame^] | 49 | if (valp == 0) { |
mcaleavya | 6959dcf | 2016-02-06 12:00:34 +0000 | [diff] [blame] | 50 | return 0; |
| 51 | } |
| 52 | |
| 53 | if (req->__data_len > 0) { |
| 54 | struct proc_key_t key = {.slot = bpf_log2l(req->__data_len / 1024)}; |
| 55 | bpf_probe_read(&key.name, sizeof(key.name),valp->name); |
| 56 | dist.increment(key); |
| 57 | } |
Brendan Gregg | 6497a84 | 2016-02-06 17:08:38 -0800 | [diff] [blame] | 58 | return 0; |
mcaleavya | 6959dcf | 2016-02-06 12:00:34 +0000 | [diff] [blame] | 59 | } |
| 60 | """ |
| 61 | |
| 62 | # load BPF program |
| 63 | b = BPF(text=bpf_text) |
| 64 | b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start") |
| 65 | b.attach_kprobe(event="blk_account_io_completion", fn_name="do_count") |
| 66 | |
| 67 | print("Tracing... Hit Ctrl-C to end.") |
| 68 | |
| 69 | # trace until Ctrl-C |
| 70 | dist = b.get_table("dist") |
| 71 | |
| 72 | try: |
| 73 | sleep(99999999) |
| 74 | except KeyboardInterrupt: |
Brendan Gregg | 6497a84 | 2016-02-06 17:08:38 -0800 | [diff] [blame] | 75 | dist.print_log2_hist("Kbytes", "Process Name") |