iostat : add -x to display extended statistics

Signed-off-by: jiaqizho <jiaqi.zhou@intel.com>
Change-Id: Ia25257093a13987c40a682c9b5ace4daa15ac607
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4847
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
jiaqizho 2020-10-23 10:23:02 +08:00 committed by Jim Harris
parent 84588b3ba8
commit 81a8bc670c

View File

@ -16,6 +16,8 @@ SPDK_BDEV_KB_STAT_HEAD = ['Device', 'tps', 'KB_read/s',
'KB_wrtn/s', 'KB_dscd/s', 'KB_read', 'KB_wrtn', 'KB_dscd']
SPDK_BDEV_MB_STAT_HEAD = ['Device', 'tps', 'MB_read/s',
'MB_wrtn/s', 'MB_dscd/s', 'MB_read', 'MB_wrtn', 'MB_dscd']
SPDK_BDEV_EXT_STAT_HEAD = ['qu-sz', 'aqu-sz', 'wareq-sz', 'rareq-sz', 'w_await(us)', 'r_await(us)', 'util']
SPDK_MAX_SECTORS = 0xffffffff
@ -25,6 +27,7 @@ class BdevStat:
def __init__(self, dictionary):
if dictionary is None:
return
self.qd_period = 0
for k, value in dictionary.items():
if k == 'name':
self.bdev_name = value
@ -46,16 +49,14 @@ class BdevStat:
self.wr_ticks = value
elif k == 'unmap_latency_ticks':
self.dc_ticks = value
elif k == 'queue_depth_polling_period':
self.qd_period = value
elif k == 'queue_depth':
self.ios_pgr = value
self.queue_depth = value
elif k == 'io_time':
self.tot_ticks = value
self.io_time = value
elif k == 'weighted_io_time':
self.rq_ticks = value
self.rd_merges = 0
self.wr_merges = 0
self.dc_merges = 0
self.weighted_io_time = value
self.upt = 0.0
def __getattr__(self, name):
@ -159,12 +160,13 @@ def get_cpu_stat():
return cpu_dump_info
def read_bdev_stat(last_stat, stat, mb, use_upt):
def read_bdev_stat(last_stat, stat, mb, use_upt, ext_info):
if use_upt:
upt_cur = uptime()
else:
upt_cur = stat['ticks']
upt_rate = stat['tick_rate']
upt_rate = stat['tick_rate']
info_stats = []
unit = 2048 if mb else 2
@ -215,6 +217,48 @@ def read_bdev_stat(last_stat, stat, mb, use_upt):
"{:.2f}".format(wr_sec / unit),
"{:.2f}".format(dc_sec / unit),
]
if ext_info:
if _stat.qd_period > 0:
tot_sampling_time = upt * 1000000 / _stat.qd_period
busy_times = (_stat.io_time - _last_stat.io_time) / _stat.qd_period
wr_ios = _stat.wr_ios - _last_stat.wr_ios
rd_ios = _stat.rd_ios - _last_stat.rd_ios
if busy_times != 0:
aqu_sz = (_stat.weighted_io_time - _last_stat.weighted_io_time) / _stat.qd_period / busy_times
else:
aqu_sz = 0
if wr_ios != 0:
wareq_sz = wr_sec / wr_ios
w_await = (_stat.wr_ticks * 1000000 / upt_rate -
_last_stat.wr_ticks * 1000000 / upt_rate) / wr_ios
else:
wareq_sz = 0
w_await = 0
if rd_ios != 0:
rareq_sz = rd_sec / rd_ios
r_await = (_stat.rd_ticks * 1000000 / upt_rate -
_last_stat.rd_ticks * 1000000 / upt_rate) / rd_ios
else:
rareq_sz = 0
r_await = 0
util = busy_times / tot_sampling_time
info_stat += [
"{:.2f}".format(_stat.queue_depth),
"{:.2f}".format(aqu_sz),
"{:.2f}".format(wareq_sz),
"{:.2f}".format(rareq_sz),
"{:.2f}".format(w_await),
"{:.2f}".format(r_await),
"{:.2f}".format(util),
]
else:
info_stat += ["N/A"] * len(SPDK_BDEV_EXT_STAT_HEAD)
info_stats.append(info_stat)
else:
for bdev in stat['bdevs']:
@ -238,10 +282,53 @@ def read_bdev_stat(last_stat, stat, mb, use_upt):
"{:.2f}".format(_stat.wr_sectors / unit),
"{:.2f}".format(_stat.dc_sectors / unit),
]
# add extended statistics
if ext_info:
if _stat.qd_period > 0:
tot_sampling_time = upt * 1000000 / _stat.qd_period
busy_times = _stat.io_time / _stat.qd_period
if busy_times != 0:
aqu_sz = _stat.weighted_io_time / _stat.qd_period / busy_times
else:
aqu_sz = 0
if _stat.wr_ios != 0:
wareq_sz = _stat.wr_sectors / _stat.wr_ios
w_await = _stat.wr_ticks * 1000000 / upt_rate / _stat.wr_ios
else:
wareq_sz = 0
w_await = 0
if _stat.rd_ios != 0:
rareq_sz = _stat.rd_sectors / _stat.rd_ios
r_await = _stat.rd_ticks * 1000000 / upt_rate / _stat.rd_ios
else:
rareq_sz = 0
r_await = 0
util = busy_times / tot_sampling_time
info_stat += [
"{:.2f}".format(_stat.queue_depth),
"{:.2f}".format(aqu_sz),
"{:.2f}".format(wareq_sz),
"{:.2f}".format(rareq_sz),
"{:.2f}".format(w_await),
"{:.2f}".format(r_await),
"{:.2f}".format(util),
]
else:
info_stat += ["N/A"] * len(SPDK_BDEV_EXT_STAT_HEAD)
info_stats.append(info_stat)
_stat_format(
info_stats, SPDK_BDEV_MB_STAT_HEAD if mb else SPDK_BDEV_KB_STAT_HEAD)
head = []
head += SPDK_BDEV_MB_STAT_HEAD if mb else SPDK_BDEV_KB_STAT_HEAD
if ext_info:
head += SPDK_BDEV_EXT_STAT_HEAD
_stat_format(info_stats, head)
return bdev_stats
@ -258,14 +345,14 @@ def io_stat_display(args, cpu_info, stat):
if args.bdev_stat and not args.cpu_stat:
_stat = get_bdev_stat(args.client, args.name)
bdev_stats = read_bdev_stat(
stat, _stat, args.mb_display, args.use_uptime)
stat, _stat, args.mb_display, args.use_uptime, args.extended_display)
return None, bdev_stats
_cpu_info = get_cpu_stat()
read_cpu_stat(cpu_info, _cpu_info)
_stat = get_bdev_stat(args.client, args.name)
bdev_stats = read_bdev_stat(stat, _stat, args.mb_display, args.use_uptime)
bdev_stats = read_bdev_stat(stat, _stat, args.mb_display, args.use_uptime, args.extended_display)
return _cpu_info, bdev_stats
@ -343,6 +430,10 @@ if __name__ == "__main__":
parser.add_argument('-v', dest='verbose', action='store_const', const="INFO",
help='Set verbose mode to INFO', default="ERROR")
parser.add_argument('-x', '--extended', dest='extended_display',
action='store_true', help="Display extended statistics.",
required=False, default=False)
args = parser.parse_args()
if ((args.interval == 0 and args.time_in_second != 0) or
(args.interval != 0 and args.time_in_second == 0)):