Skip to content

Instantly share code, notes, and snippets.

@jsharkey13
Created January 18, 2024 11:37
Show Gist options
  • Save jsharkey13/4efafa299b334b40b329ebc57ef0a3e4 to your computer and use it in GitHub Desktop.
Save jsharkey13/4efafa299b334b40b329ebc57ef0a3e4 to your computer and use it in GitHub Desktop.
Analyse zpool disk latencies with graphical output.
# zpool disk latency visualisation
#
# This script parses the output of the zpool stats command:
# zpool iostat -pvwH
# which provides per-disk latency information for reads and writes.
#
# Run the command:
#
# zpool iostat -pvwH > output.tsv
#
# and copy the resulting file to the same folder as this script, then run
# this script.
#
# The ["tank"] list can be replaced by any names to exclude (i.e. the pool and groups)
# and "zpool" can be changed to an appropriate title.
#
import matplotlib.pyplot as plt
import numpy as np
__all__ = ["parse_output", "display_graphs"]
COLUMN_HEADINGS = ["total_wait:read", "total_wait:write",
"disk_wait:read", "disk_wait:write",
"syncq_wait:read", "syncq_wait:write",
"asyncq_wait:read", "asyncq_wait:write",
"scrub", "trim"]
BUCKETS = ["1ns", "3ns", "7ns", "15ns", "31ns", "63ns", "127ns", "255ns", "511ns",
"1us", "2us", "4us", "8us", "16us", "32us", "65us", "131us", "262us", "524us",
"1ms", "2ms", "4ms", "8ms", "16ms", "33ms", "67ms", "134ms", "268ms", "536ms",
"1s", "2s", "4s", "8s", "17s", "34s", "68s", "137s"]
COLOURS = ["red", "darkorange", "gold", "greenyellow", "seagreen", "turquoise", "royalblue", "rebeccapurple"]
def _parse_histogram_rows(tsv_rows):
results = dict()
for row in tsv_rows:
bucket, *data = row.split("\t")
assert len(data) == len(COLUMN_HEADINGS), f"Expected {len(COLUMN_HEADINGS)} columns, found {len(data)}!"
results[bucket] = dict(zip(COLUMN_HEADINGS, map(int, data)))
assert len(results) == len(BUCKETS), f"Expected {len(BUCKETS)} rows, found {len(results)}!"
return results
def parse_output(tsv_value):
"""Parse the output of `zpool iostat -pwvH` into a dictionary."""
results = dict()
for section_value_str in tsv_value.split("\n\n"):
section_value = section_value_str.strip()
if section_value == "":
continue
title, *histogram_rows = section_value.split("\n")
results[title] = _parse_histogram_rows(histogram_rows)
return results
def display_graphs(zpool_stats, *, name="", include_disks=None):
"""Plot the latency stats for a group of disks."""
if include_disks is None:
include_disks = zpool_stats.keys()
for col in COLUMN_HEADINGS:
n_disks = len(include_disks)
width = round(1 / (n_disks + 2), 3)
bin_positions = np.arange(len(BUCKETS))
fig, ax = plt.subplots()
fig.set_size_inches(20, 8)
figtitle = f"{name} {col}"
fig.suptitle(figtitle, fontsize=20)
handles = []
for i, disk in enumerate(include_disks):
data = [r[col] for r in zpool_stats[disk].values()]
if sum(data) == 0:
# Skip all-blank groups.
continue
x_positions = bin_positions + (i-(n_disks // 2))*width # Shift bars around centre of the bin.
h = ax.bar(x_positions, data, width, color=COLOURS[i])
handles.append(h)
ax.set_xticks(range(len(BUCKETS))[::2]) # Too crowded with every bin labelled.
ax.set_xticklabels(BUCKETS[::2])
ax.semilogy()
ax.legend(handles=handles, labels=include_disks)
plt.show()
if __name__ == "__main__":
# Run `zpool iostat -pwvH > output.tsv`.
with open("output.tsv") as f:
stats = parse_output(f.read())
disks = [d for d in stats.keys() if d not in ["tank"]] # Exclude whole-pool stats?
display_graphs(stats, name="zpool", include_disks=disks)
@jsharkey13
Copy link
Author

It is much easier to see which disk is bad at a glance from this:

example-bad-disk

than by comparing the bad disk output section:

sdc            total_wait         disk_wait        syncq_wait        asyncq_wait
latency        read    write     read    write     read    write     read    write    scrub     trim
----------  -------  -------  -------  -------  -------  -------  -------  -------  -------  -------
1ns               0        0        0        0        0        0        0        0        0        0
3ns               0        0        0        0        0        0        0        0        0        0
7ns               0        0        0        0        0        0        0        0        0        0
15ns              0        0        0        0        0        0        0        0        0        0
31ns              0        0        0        0        0        0        0        0        0        0
63ns              0        0        0        0        0        0        0        0        0        0
127ns             0        0        0        0        0        0        0        0        0        0
255ns             0        0        0        0        0        0        0        0        0        0
511ns             0        0        0        0        0        0        0        0        0        0
1us               0        0        0        0       34      852     3139       18        1        0
2us               0        0        0        0     4754   552461    48607    16422        7        0
4us               0        0        0        0    29773   315261    27451   233723        3        0
8us               0        0        0        0     7281   128159      890   248969        0        0
16us              0        0        0        0      116     2254      250    41496        0        0
32us              0        0        0        0       59     2367      349    28117        0        0
65us              0       13        0       35       19     1108      456    48120        0        0
131us         42092      533    43588     1283       26      787      804    90961        0        0
262us         28532   430768    27424   727579       25      698      809   221581        0        0
524us          9140   879561     9223  2024834       13      430      529   285668        0        0
1ms            4031   599940     4388   363562       10      278      543   390534        0        0
2ms            2291   711408     2561   251741       10      321      568   531157        1        0
4ms            2507   569031     2911   109908       27      250      610   361589        0        0
8ms            6144   205205     6505   119815       56      167      869    94943        5        0
16ms          15158   128052    15298    66397       89      195     1408    42488        7        0
33ms          10383    64147    10635    30367      160      216     1061    30453        7        0
67ms           5143    68540     4463    32226      138      277      596    38798        5        0
134ms          2924    87359     2472    31857      110      150      413    54241        6        0
268ms           618     8722      504     2666       47       53       46     4893        0        0
536ms           104     1811       79     1177        9       29        9      585        0        0
1s              116     2125      114     1806        1       54        1      321        0        0
2s              371     4224      343     4016       26       60       13      227        0        0
4s             3351    16202     2529     9232      308      114      534     6869       13        0
8s              268     1746      161      943        8        8       71      762        0        0
17s              27      109        3       66        6        0       16       36        0        0
34s               2       30        1       16        0        0        0       13        0        0
68s               0        6        0        6        0        0        0        0        0        0
137s              0        2        0        2        0        0        0        0        0        0
----------------------------------------------------------------------------------------------------

to another disk output section

sdb            total_wait         disk_wait        syncq_wait        asyncq_wait
latency        read    write     read    write     read    write     read    write    scrub     trim
----------  -------  -------  -------  -------  -------  -------  -------  -------  -------  -------
1ns               0        0        0        0        0        0        0        0        0        0
3ns               0        0        0        0        0        0        0        0        0        0
7ns               0        0        0        0        0        0        0        0        0        0
15ns              0        0        0        0        0        0        0        0        0        0
31ns              0        0        0        0        0        0        0        0        0        0
63ns              0        0        0        0        0        0        0        0        0        0
127ns             0        0        0        0        0        0        0        0        0        0
255ns             0        0        0        0        0        0        0        0        0        0
511ns             0        0        0        0        0        0        0        0        0        0
1us               0        0        0        0       45      703     3480       20        0        0
2us               0        0        0        0     4757   485975    54155    16341       17        0
4us               0        0        0        0    31168   389054    37219   243307        6        0
8us               0        0        0        0     6717   131556      905   257919        2        0
16us              0        0        0        0      112     2333      249    42486        0        0
32us              0        0        0        0       65     2217      330    29683        0        0
65us              0       13        0       52       17     1017      470    50529        2        0
131us         48045      650    49879     1453       17      741      723    94808        3        0
262us         37947   471147    36405   778194       12      659      668   228437        6        0
524us          9737   888983     9789  2040290        5      447      424   293845        3        0
1ms            4312   620738     4719   365167        0      275      401   396638        1        0
2ms            2261   719469     2620   255409        6      314      455   533000        1        0
4ms            2552   573456     3026   112430        2      236      542   363958        3        0
8ms            7287   203979     7582   117527        5      152      940    93438        9        0
16ms          17486   117752    17307    60550       16      161     1390    37566       21        0
33ms          10723    65520    10428    31595       24      189      822    30163       10        0
67ms           3957    71847     3253    32600        8      219      441    40819       18        0
134ms          2396    86858     1879    30690        2      163      398    54289       10        0
268ms           417     6717      271     1686        3       21       50     3960        0        0
536ms            47      666       18      315        1       18       21      314        0        0
1s               17      332        8      169        0        0        7      159        0        0
2s                0        2        0        2        0        0        0        0        0        0
4s                0        0        0        0        0        0        0        0        0        0
8s                0        0        0        0        0        0        0        0        0        0
17s               0        0        0        0        0        0        0        0        0        0
34s               0        0        0        0        0        0        0        0        0        0
68s               0        0        0        0        0        0        0        0        0        0
137s              0        0        0        0        0        0        0        0        0        0
----------------------------------------------------------------------------------------------------

and the remaining disk sections too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment