Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

biolatency: add -F for I/O flags #2280

Merged
merged 1 commit into from
Mar 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
biolatency: add -F for I/O flags
  • Loading branch information
brendangregg committed Mar 20, 2019
commit b26e5ef92f96058e40ef080d9c9505b7ce0a7ce7
5 changes: 4 additions & 1 deletion man/man8/biolatency.8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.SH NAME
biolatency \- Summarize block device I/O latency as a histogram.
.SH SYNOPSIS
.B biolatency [\-h] [\-T] [\-Q] [\-m] [\-D] [interval [count]]
.B biolatency [\-h] [\-F] [\-T] [\-Q] [\-m] [\-D] [interval [count]]
.SH DESCRIPTION
biolatency traces block device I/O (disk I/O), and records the distribution
of I/O latency (time). This is printed as a histogram either on Ctrl-C, or
Expand Down Expand Up @@ -33,6 +33,9 @@ Output histogram in milliseconds.
\-D
Print a histogram per disk device.
.TP
\-F
Print a histogram per set of I/O flags.
.TP
interval
Output interval, in seconds.
.TP
Expand Down
74 changes: 73 additions & 1 deletion tools/biolatency.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
./biolatency -mT 1 # 1s summaries, milliseconds, and timestamps
./biolatency -Q # include OS queued time in I/O time
./biolatency -D # show each disk device separately
./biolatency -F # show I/O flags separately
"""
parser = argparse.ArgumentParser(
description="Summarize block device I/O latency as a histogram",
Expand All @@ -36,6 +37,8 @@
help="millisecond histogram")
parser.add_argument("-D", "--disks", action="store_true",
help="print a histogram per disk device")
parser.add_argument("-F", "--flags", action="store_true",
help="print a histogram per set of I/O flags")
parser.add_argument("interval", nargs="?", default=99999999,
help="output interval, in seconds")
parser.add_argument("count", nargs="?", default=99999999,
Expand All @@ -45,6 +48,9 @@
args = parser.parse_args()
countdown = int(args.count)
debug = 0
if args.flags and args.disks:
print("ERROR: can only use -D or -F. Exiting.")
exit()

# define BPF program
bpf_text = """
Expand All @@ -55,6 +61,12 @@
char disk[DISK_NAME_LEN];
u64 slot;
} disk_key_t;

typedef struct flag_key {
u64 flags;
u64 slot;
} flag_key_t;

BPF_HASH(start, struct request *);
STORAGE

Expand Down Expand Up @@ -102,6 +114,13 @@
'void *__tmp = (void *)req->rq_disk->disk_name; ' +
'bpf_probe_read(&key.disk, sizeof(key.disk), __tmp); ' +
'dist.increment(key);')
elif args.flags:
bpf_text = bpf_text.replace('STORAGE',
'BPF_HISTOGRAM(dist, flag_key_t);')
bpf_text = bpf_text.replace('STORE',
'flag_key_t key = {.slot = bpf_log2l(delta)}; ' +
'key.flags = req->cmd_flags; ' +
'dist.increment(key);')
else:
bpf_text = bpf_text.replace('STORAGE', 'BPF_HISTOGRAM(dist);')
bpf_text = bpf_text.replace('STORE',
Expand All @@ -124,6 +143,56 @@

print("Tracing block device I/O... Hit Ctrl-C to end.")

# see blk_fill_rwbs():
req_opf = {
0: "Read",
1: "Write",
2: "Flush",
3: "Discard",
5: "SecureErase",
6: "ZoneReset",
7: "WriteSame",
9: "WriteZeros"
}
REQ_OP_BITS = 8
REQ_OP_MASK = ((1 << REQ_OP_BITS) - 1)
REQ_SYNC = 1 << (REQ_OP_BITS + 3)
REQ_META = 1 << (REQ_OP_BITS + 4)
REQ_PRIO = 1 << (REQ_OP_BITS + 5)
REQ_NOMERGE = 1 << (REQ_OP_BITS + 6)
REQ_IDLE = 1 << (REQ_OP_BITS + 7)
REQ_FUA = 1 << (REQ_OP_BITS + 9)
REQ_RAHEAD = 1 << (REQ_OP_BITS + 11)
REQ_BACKGROUND = 1 << (REQ_OP_BITS + 12)
REQ_NOWAIT = 1 << (REQ_OP_BITS + 13)
def flags_print(flags):
desc = ""
# operation
if flags & REQ_OP_MASK in req_opf:
desc = req_opf[flags & REQ_OP_MASK]
else:
desc = "Unknown"
# flags
if flags & REQ_SYNC:
desc = "Sync-" + desc
if flags & REQ_META:
desc = "Metadata-" + desc
if flags & REQ_FUA:
desc = "ForcedUnitAccess-" + desc
if flags & REQ_PRIO:
desc = "Priority-" + desc
if flags & REQ_NOMERGE:
desc = "NoMerge-" + desc
if flags & REQ_IDLE:
desc = "Idle-" + desc
if flags & REQ_RAHEAD:
desc = "ReadAhead-" + desc
if flags & REQ_BACKGROUND:
desc = "Background-" + desc
if flags & REQ_NOWAIT:
desc = "NoWait-" + desc
return desc

# output
exiting = 0 if args.interval else 1
dist = b.get_table("dist")
Expand All @@ -137,7 +206,10 @@
if args.timestamp:
print("%-8s\n" % strftime("%H:%M:%S"), end="")

dist.print_log2_hist(label, "disk")
if args.flags:
dist.print_log2_hist(label, "flags", flags_print)
else:
dist.print_log2_hist(label, "disk")
dist.clear()

countdown -= 1
Expand Down
99 changes: 98 additions & 1 deletion tools/biolatency_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,105 @@ This output sows that xvda1 has much higher latency, usually between 0.5 ms
and 32 ms, whereas xvdc is usually between 0.2 ms and 4 ms.


The -F option prints a separate histogram for each unique set of request
flags. For example:

./biolatency.py -Fm
Tracing block device I/O... Hit Ctrl-C to end.
^C

flags = Read
msecs : count distribution
0 -> 1 : 180 |************* |
2 -> 3 : 519 |****************************************|
4 -> 7 : 60 |**** |
8 -> 15 : 123 |********* |
16 -> 31 : 68 |***** |
32 -> 63 : 0 | |
64 -> 127 : 2 | |
128 -> 255 : 12 | |
256 -> 511 : 0 | |
512 -> 1023 : 1 | |

flags = Sync-Write
msecs : count distribution
0 -> 1 : 5 |****************************************|

flags = Flush
msecs : count distribution
0 -> 1 : 2 |****************************************|

flags = Metadata-Read
msecs : count distribution
0 -> 1 : 3 |****************************************|
2 -> 3 : 2 |************************** |
4 -> 7 : 0 | |
8 -> 15 : 1 |************* |
16 -> 31 : 1 |************* |

flags = Write
msecs : count distribution
0 -> 1 : 103 |******************************* |
2 -> 3 : 106 |******************************** |
4 -> 7 : 130 |****************************************|
8 -> 15 : 79 |************************ |
16 -> 31 : 5 |* |
32 -> 63 : 0 | |
64 -> 127 : 0 | |
128 -> 255 : 0 | |
256 -> 511 : 1 | |

flags = NoMerge-Read
msecs : count distribution
0 -> 1 : 0 | |
2 -> 3 : 5 |****************************************|
4 -> 7 : 0 | |
8 -> 15 : 0 | |
16 -> 31 : 1 |******** |

flags = NoMerge-Write
msecs : count distribution
0 -> 1 : 30 |** |
2 -> 3 : 293 |******************** |
4 -> 7 : 564 |****************************************|
8 -> 15 : 463 |******************************** |
16 -> 31 : 21 |* |
32 -> 63 : 0 | |
64 -> 127 : 0 | |
128 -> 255 : 0 | |
256 -> 511 : 5 | |

flags = Priority-Metadata-Read
msecs : count distribution
0 -> 1 : 1 |****************************************|
2 -> 3 : 0 | |
4 -> 7 : 1 |****************************************|
8 -> 15 : 1 |****************************************|

flags = ForcedUnitAccess-Metadata-Sync-Write
msecs : count distribution
0 -> 1 : 2 |****************************************|

flags = ReadAhead-Read
msecs : count distribution
0 -> 1 : 15 |*************************** |
2 -> 3 : 22 |****************************************|
4 -> 7 : 14 |************************* |
8 -> 15 : 8 |************** |
16 -> 31 : 1 |* |

flags = Priority-Metadata-Write
msecs : count distribution
0 -> 1 : 9 |****************************************|

These can be handled differently by the storage device, and this mode lets us
examine their performance in isolation.


USAGE message:

# ./biolatency -h
usage: biolatency [-h] [-T] [-Q] [-m] [-D] [interval] [count]
usage: biolatency [-h] [-T] [-Q] [-m] [-D] [-F] [interval] [count]

Summarize block device I/O latency as a histogram

Expand All @@ -215,10 +310,12 @@ optional arguments:
-Q, --queued include OS queued time in I/O time
-m, --milliseconds millisecond histogram
-D, --disks print a histogram per disk device
-F, --flags print a histogram per set of I/O flags

examples:
./biolatency # summarize block I/O latency as a histogram
./biolatency 1 10 # print 1 second summaries, 10 times
./biolatency -mT 1 # 1s summaries, milliseconds, and timestamps
./biolatency -Q # include OS queued time in I/O time
./biolatency -D # show each disk device separately
./biolatency -F # show I/O flags separately