Last active
May 12, 2021 21:20
-
-
Save nijave/989bda8b1a512d44b3016840d8efe3dc to your computer and use it in GitHub Desktop.
Rudimentary iostat in Python to demo sysfs block device stats
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # pyiostat | |
| import os | |
| import time | |
| from pprint import pprint | |
| # https://www.kernel.org/doc/html/latest/block/stat.html | |
| stat_labels_extended = [ | |
| # reads | |
| "read I/Os", # number of read I/Os processed | |
| "read merges", # number of read I/Os merged with in-queue I/O | |
| "read sectors", # number of sectors read | |
| "read ticks", # total wait time for read requests | |
| # writes | |
| "write I/Os", | |
| "write merges", | |
| "write sectors", | |
| "write ticks", | |
| # overall | |
| "in_flight", # number of I/Os currently in flight | |
| "io_ticks", # total time this block device has been active | |
| "time_in_queue", # total wait time for all requests | |
| # discards | |
| "discard I/Os", | |
| "discard merges", | |
| "discard sectors", | |
| "discard ticks", | |
| # flushes | |
| "flush I/Os", # number of flush I/Os processed | |
| "flush ticks", # total wait time for flush request | |
| ] | |
| stat_labels_basic = [ | |
| "read I/Os", | |
| "read sectors", | |
| "write I/Os", | |
| "write sectors", | |
| ] | |
| def get_stats(): | |
| all_stats = {} | |
| for dev in filter(lambda d: any(d.startswith(prefix) for prefix in ("nvme", "sd")), os.listdir("/sys/block")): | |
| with open(os.path.join("/sys/block", dev, "stat"), "r") as f: | |
| stats = [float(s) for s in f.read().strip().split()] | |
| labels = stat_labels_basic if len(stats) == len(stat_labels_basic) else stat_labels_extended | |
| stat_table = dict(zip(labels[0:len(stats)], stats)) | |
| all_stats[dev] = stat_table | |
| return all_stats | |
| def diff_stats(left, right, drop_empty=True): | |
| all_diff = {} | |
| for dev in left: | |
| if dev not in right: | |
| print(f"{dev} missing") | |
| continue | |
| all_diff[dev] = {} | |
| for attr in left[dev]: | |
| if attr not in right[dev]: | |
| print(f"{dev} missing {attr}") | |
| continue | |
| all_diff[dev][attr] = right[dev][attr] - left[dev][attr] | |
| if drop_empty and all(attr == 0 for attr in all_diff[dev].values()): | |
| del all_diff[dev] | |
| return all_diff | |
| def compare(interval=1): | |
| first = get_stats() | |
| time.sleep(interval) | |
| second = get_stats() | |
| return diff_stats(first, second) | |
| for _ in range(10): | |
| pprint(compare()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment