Skip to content

Commit

Permalink
fix pep8 lint errors in biolatency and biosnoop
Browse files Browse the repository at this point in the history
Signed-off-by: Alexei Starovoitov <[email protected]>
  • Loading branch information
4ast committed Jan 9, 2016
1 parent 1ec515e commit a79da0a
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 134 deletions.
117 changes: 59 additions & 58 deletions tools/biolatency
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# biolatency Summarize block device I/O latency as a histogram.
# For Linux, uses BCC, eBPF.
# biolatency Summarize block device I/O latency as a histogram.
# For Linux, uses BCC, eBPF.
#
# USAGE: biolatency [-h] [-T] [-Q] [-m] [-D] [interval] [count]
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 20-Sep-2015 Brendan Gregg Created this.
# 20-Sep-2015 Brendan Gregg Created this.

from __future__ import print_function
from bcc import BPF
Expand All @@ -24,21 +25,21 @@ examples = """examples:
./biolatency -D # show each disk device separately
"""
parser = argparse.ArgumentParser(
description="Summarize block device I/O latency as a histogram",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=examples)
description="Summarize block device I/O latency as a histogram",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=examples)
parser.add_argument("-T", "--timestamp", action="store_true",
help="include timestamp on output")
help="include timestamp on output")
parser.add_argument("-Q", "--queued", action="store_true",
help="include OS queued time in I/O time")
help="include OS queued time in I/O time")
parser.add_argument("-m", "--milliseconds", action="store_true",
help="millisecond histogram")
help="millisecond histogram")
parser.add_argument("-D", "--disks", action="store_true",
help="print a histogram per disk device")
help="print a histogram per disk device")
parser.add_argument("interval", nargs="?", default=99999999,
help="output interval, in seconds")
help="output interval, in seconds")
parser.add_argument("count", nargs="?", default=99999999,
help="number of outputs")
help="number of outputs")
args = parser.parse_args()
countdown = int(args.count)
debug = 0
Expand All @@ -49,69 +50,69 @@ bpf_text = """
#include <linux/blkdev.h>
typedef struct disk_key {
char disk[DISK_NAME_LEN];
u64 slot;
char disk[DISK_NAME_LEN];
u64 slot;
} disk_key_t;
BPF_HASH(start, struct request *);
STORAGE
// time block I/O
int trace_req_start(struct pt_regs *ctx, struct request *req)
{
u64 ts = bpf_ktime_get_ns();
start.update(&req, &ts);
return 0;
u64 ts = bpf_ktime_get_ns();
start.update(&req, &ts);
return 0;
}
// output
int trace_req_completion(struct pt_regs *ctx, struct request *req)
{
u64 *tsp, delta;
u64 *tsp, delta;
// fetch timestamp and calculate delta
tsp = start.lookup(&req);
if (tsp == 0) {
return 0; // missed issue
}
delta = bpf_ktime_get_ns() - *tsp;
FACTOR
// fetch timestamp and calculate delta
tsp = start.lookup(&req);
if (tsp == 0) {
return 0; // missed issue
}
delta = bpf_ktime_get_ns() - *tsp;
FACTOR
// store as histogram
STORE
// store as histogram
STORE
start.delete(&req);
return 0;
start.delete(&req);
return 0;
}
"""

# code substitutions
if args.milliseconds:
bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000000;')
label = "msecs"
bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000000;')
label = "msecs"
else:
bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000;')
label = "usecs"
bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000;')
label = "usecs"
if args.disks:
bpf_text = bpf_text.replace('STORAGE',
'BPF_HISTOGRAM(dist, disk_key_t);')
bpf_text = bpf_text.replace('STORE',
'disk_key_t key = {.slot = bpf_log2l(delta)}; ' +
'bpf_probe_read(&key.disk, sizeof(key.disk), ' +
'req->rq_disk->disk_name); dist.increment(key);')
bpf_text = bpf_text.replace('STORAGE',
'BPF_HISTOGRAM(dist, disk_key_t);')
bpf_text = bpf_text.replace('STORE',
'disk_key_t key = {.slot = bpf_log2l(delta)}; ' +
'bpf_probe_read(&key.disk, sizeof(key.disk), ' +
'req->rq_disk->disk_name); dist.increment(key);')
else:
bpf_text = bpf_text.replace('STORAGE', 'BPF_HISTOGRAM(dist);')
bpf_text = bpf_text.replace('STORE',
'dist.increment(bpf_log2l(delta));')
bpf_text = bpf_text.replace('STORAGE', 'BPF_HISTOGRAM(dist);')
bpf_text = bpf_text.replace('STORE',
'dist.increment(bpf_log2l(delta));')
if debug:
print(bpf_text)
print(bpf_text)

# load BPF program
b = BPF(text=bpf_text)
if args.queued:
b.attach_kprobe(event="blk_account_io_start", fn_name="trace_req_start")
b.attach_kprobe(event="blk_account_io_start", fn_name="trace_req_start")
else:
b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start")
b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start")
b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start")
b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start")
b.attach_kprobe(event="blk_account_io_completion",
fn_name="trace_req_completion")

Expand All @@ -121,18 +122,18 @@ print("Tracing block device I/O... Hit Ctrl-C to end.")
exiting = 0 if args.interval else 1
dist = b.get_table("dist")
while (1):
try:
sleep(int(args.interval))
except KeyboardInterrupt:
exiting=1
try:
sleep(int(args.interval))
except KeyboardInterrupt:
exiting = 1

print()
if args.timestamp:
print("%-8s\n" % strftime("%H:%M:%S"), end="")
print()
if args.timestamp:
print("%-8s\n" % strftime("%H:%M:%S"), end="")

dist.print_log2_hist(label, "disk")
dist.clear()
dist.print_log2_hist(label, "disk")
dist.clear()

countdown -= 1
if exiting or countdown == 0:
exit()
countdown -= 1
if exiting or countdown == 0:
exit()
143 changes: 72 additions & 71 deletions tools/biosnoop
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#!/usr/bin/python
# @lint-avoid-python-3-compatibility-imports
#
# biosnoop Trace block device I/O and print details including issuing PID.
# For Linux, uses BCC, eBPF.
# biosnoop Trace block device I/O and print details including issuing PID.
# For Linux, uses BCC, eBPF.
#
# This uses in-kernel eBPF maps to cache process details (PID and comm) by I/O
# request, as well as a starting timestamp for calculating I/O latency.
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 16-Sep-2015 Brendan Gregg Created this.
# 16-Sep-2015 Brendan Gregg Created this.

from __future__ import print_function
from bcc import BPF
Expand All @@ -20,7 +21,7 @@ b = BPF(text="""
#include <linux/blkdev.h>
struct val_t {
char name[TASK_COMM_LEN];
char name[TASK_COMM_LEN];
};
BPF_HASH(start, struct request *);
Expand All @@ -30,74 +31,74 @@ BPF_HASH(commbyreq, struct request *, struct val_t);
// cache PID and comm by-req
int trace_pid_start(struct pt_regs *ctx, struct request *req)
{
u32 pid;
struct val_t val = {};
u32 pid;
struct val_t val = {};
pid = bpf_get_current_pid_tgid();
pidbyreq.update(&req, &pid);
if (bpf_get_current_comm(&val.name, sizeof(val.name)) == 0) {
commbyreq.update(&req, &val);
}
pid = bpf_get_current_pid_tgid();
pidbyreq.update(&req, &pid);
if (bpf_get_current_comm(&val.name, sizeof(val.name)) == 0) {
commbyreq.update(&req, &val);
}
return 0;
return 0;
}
// time block I/O
int trace_req_start(struct pt_regs *ctx, struct request *req)
{
u64 ts;
u64 ts;
ts = bpf_ktime_get_ns();
start.update(&req, &ts);
ts = bpf_ktime_get_ns();
start.update(&req, &ts);
return 0;
return 0;
}
// output
int trace_req_completion(struct pt_regs *ctx, struct request *req)
{
u64 *tsp, delta;
u32 *pidp = 0;
struct val_t *valp;
// fetch timestamp and calculate delta
tsp = start.lookup(&req);
if (tsp == 0) {
// missed tracing issue
return 0;
}
delta = bpf_ktime_get_ns() - *tsp;
//
// Fetch and output issuing pid and comm.
// As bpf_trace_prink() is limited to a maximum of 1 string and 2
// integers, we'll use more than one to output the data.
//
valp = commbyreq.lookup(&req);
pidp = pidbyreq.lookup(&req);
if (pidp == 0 || valp == 0) {
bpf_trace_printk("0 0 ? %d\\n", req->__data_len);
} else {
bpf_trace_printk("0 %d %s %d\\n", *pidp, valp->name,
req->__data_len);
}
// output remaining details
if (req->cmd_flags & REQ_WRITE) {
bpf_trace_printk("1 W %s %d %d ?\\n", req->rq_disk->disk_name,
req->__sector, delta / 1000);
} else {
bpf_trace_printk("1 R %s %d %d ?\\n", req->rq_disk->disk_name,
req->__sector, delta / 1000);
}
start.delete(&req);
pidbyreq.delete(&req);
commbyreq.delete(&req);
return 0;
u64 *tsp, delta;
u32 *pidp = 0;
struct val_t *valp;
// fetch timestamp and calculate delta
tsp = start.lookup(&req);
if (tsp == 0) {
// missed tracing issue
return 0;
}
delta = bpf_ktime_get_ns() - *tsp;
//
// Fetch and output issuing pid and comm.
// As bpf_trace_prink() is limited to a maximum of 1 string and 2
// integers, we'll use more than one to output the data.
//
valp = commbyreq.lookup(&req);
pidp = pidbyreq.lookup(&req);
if (pidp == 0 || valp == 0) {
bpf_trace_printk("0 0 ? %d\\n", req->__data_len);
} else {
bpf_trace_printk("0 %d %s %d\\n", *pidp, valp->name,
req->__data_len);
}
// output remaining details
if (req->cmd_flags & REQ_WRITE) {
bpf_trace_printk("1 W %s %d %d ?\\n", req->rq_disk->disk_name,
req->__sector, delta / 1000);
} else {
bpf_trace_printk("1 R %s %d %d ?\\n", req->rq_disk->disk_name,
req->__sector, delta / 1000);
}
start.delete(&req);
pidbyreq.delete(&req);
commbyreq.delete(&req);
return 0;
}
""")
""", debug=0)
b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start")
b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start")
b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start")
Expand All @@ -112,21 +113,21 @@ start_ts = 0

# format output
while 1:
(task, pid, cpu, flags, ts, msg) = b.trace_fields()
args = msg.split(" ")
(task, pid, cpu, flags, ts, msg) = b.trace_fields()
args = msg.split(" ")

if start_ts == 0:
start_ts = ts
if start_ts == 0:
start_ts = ts

if args[0] == "0":
(real_pid, real_comm, bytes_s) = (args[1], args[2], args[3])
continue
else:
(type_s, disk_s, sector_s, us_s) = (args[1], args[2], args[3],
args[4])
if args[0] == "0":
(real_pid, real_comm, bytes_s) = (args[1], args[2], args[3])
continue
else:
(type_s, disk_s, sector_s, us_s) = (args[1], args[2], args[3],
args[4])

ms = float(int(us_s, 10)) / 1000
ms = float(int(us_s, 10)) / 1000

print("%-14.9f %-14.14s %-6s %-7s %-2s %-9s %-7s %7.2f" % (
ts - start_ts, real_comm, real_pid, disk_s, type_s, sector_s,
bytes_s, ms))
print("%-14.9f %-14.14s %-6s %-7s %-2s %-9s %-7s %7.2f" % (
ts - start_ts, real_comm, real_pid, disk_s, type_s, sector_s,
bytes_s, ms))
10 changes: 5 additions & 5 deletions tools/biosnoop_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ $ iostat -x 1
avg-cpu: %user %nice %system %iowait %steal %idle
0.12 0.00 0.12 0.00 0.00 99.75

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvda 0.00 0.00 0.00 4.00 0.00 16.00 8.00 0.00 0.00 0.00 0.00 0.00 0.00
xvdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
xvdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
md0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s await svctm %util
xvda 0.00 0.00 0.00 4.00 0.00 16.00 0.00 0.00 0.00
xvdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
xvdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
md0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

There are 4 write IOPS.

Expand Down

0 comments on commit a79da0a

Please sign in to comment.