From: Steve Dickson <steved@redhat.com>
To: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [PATCH] nfs-utils: add option to display throughput in MB/s
Date: Wed, 6 May 2026 16:33:12 -0400 [thread overview]
Message-ID: <32b6dcdc-c7af-4e2e-8639-06e590f82599@redhat.com> (raw)
In-Reply-To: <20260501205604.653238-1-tigran.mkrtchyan@desy.de>
On 5/1/26 4:56 PM, Tigran Mkrtchyan wrote:
> Nowadays,the network bandwidth in kB/s is quite a large number to read.
> Thus, let nfsiostat display it in MB/s if requested.
>
> Signed-off-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
Committed... (tag: nfs-utils-2-9-2-rc2)
steved.
> ---
> tools/nfs-iostat/nfs-iostat.py | 53 ++++++++++++++++++++++------------
> tools/nfs-iostat/nfsiostat.man | 11 ++++---
> 2 files changed, 42 insertions(+), 22 deletions(-)
>
> diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
> index 69d24a11..af04aac5 100755
> --- a/tools/nfs-iostat/nfs-iostat.py
> +++ b/tools/nfs-iostat/nfs-iostat.py
> @@ -327,7 +327,7 @@ class DeviceData:
> print()
> print('%d congestion waits' % congestionwaits)
>
> - def __print_rpc_op_stats(self, op, sample_time):
> + def __print_rpc_op_stats(self, op, sample_time, use_mb=False):
> """Print generic stats for one RPC op
> """
> if op not in self.__rpc_data:
> @@ -343,9 +343,19 @@ class DeviceData:
> if len(rpc_stats) >= 9:
> errs = float(rpc_stats[8])
>
> + # scale to MB if requested
> + if use_mb:
> + throughput = kilobytes / 1024.0
> + throughput_label = 'MB/s'
> + per_op_label = 'MB/op'
> + else:
> + throughput = kilobytes
> + throughput_label = 'kB/s'
> + per_op_label = 'kB/op'
> +
> # prevent floating point exceptions
> if ops != 0:
> - kb_per_op = kilobytes / ops
> + unit_per_op = throughput / ops
> retrans_percent = (retrans * 100) / ops
> rtt_per_op = rtt / ops
> exe_per_op = exe / ops
> @@ -353,7 +363,7 @@ class DeviceData:
> if len(rpc_stats) >= 9:
> errs_percent = (errs * 100) / ops
> else:
> - kb_per_op = 0.0
> + unit_per_op = 0.0
> retrans_percent = 0.0
> rtt_per_op = 0.0
> exe_per_op = 0.0
> @@ -364,8 +374,8 @@ class DeviceData:
> op += ':'
> print(format(op.lower(), '<16s'), end='')
> print(format('ops/s', '>8s'), end='')
> - print(format('kB/s', '>16s'), end='')
> - print(format('kB/op', '>16s'), end='')
> + print(format(throughput_label, '>16s'), end='')
> + print(format(per_op_label, '>16s'), end='')
> print(format('retrans', '>16s'), end='')
> print(format('avg RTT (ms)', '>16s'), end='')
> print(format('avg exe (ms)', '>16s'), end='')
> @@ -375,8 +385,8 @@ class DeviceData:
> print()
>
> print(format((ops / sample_time), '>24.3f'), end='')
> - print(format((kilobytes / sample_time), '>16.3f'), end='')
> - print(format(kb_per_op, '>16.3f'), end='')
> + print(format((throughput / sample_time), '>16.3f'), end='')
> + print(format(unit_per_op, '>16.3f'), end='')
> retransmits = '{0:>10.0f} ({1:>3.1f}%)'.format(retrans, retrans_percent).strip()
> print(format(retransmits, '>16'), end='')
> print(format(rtt_per_op, '>16.3f'), end='')
> @@ -395,9 +405,11 @@ class DeviceData:
> sample_time = 1;
> return (sends / sample_time)
>
> - def display_iostats(self, sample_time, which):
> + def display_iostats(self, sample_time, options):
> """Display NFS and RPC stats in an iostat-like way
> """
> + which = options.which
> + use_mb = options.megabytes
> sends = float(self.__rpc_data['rpcsends'])
> if sample_time == 0:
> sample_time = float(self.__nfs_data['age'])
> @@ -423,21 +435,21 @@ class DeviceData:
> print()
>
> if which == 0:
> - self.__print_rpc_op_stats('READ', sample_time)
> - self.__print_rpc_op_stats('WRITE', sample_time)
> + self.__print_rpc_op_stats('READ', sample_time, use_mb)
> + self.__print_rpc_op_stats('WRITE', sample_time, use_mb)
> elif which == 1:
> - self.__print_rpc_op_stats('GETATTR', sample_time)
> - self.__print_rpc_op_stats('ACCESS', sample_time)
> + self.__print_rpc_op_stats('GETATTR', sample_time, use_mb)
> + self.__print_rpc_op_stats('ACCESS', sample_time, use_mb)
> self.__print_attr_cache_stats(sample_time)
> elif which == 2:
> - self.__print_rpc_op_stats('LOOKUP', sample_time)
> - self.__print_rpc_op_stats('READDIR', sample_time)
> + self.__print_rpc_op_stats('LOOKUP', sample_time, use_mb)
> + self.__print_rpc_op_stats('READDIR', sample_time, use_mb)
> if 'READDIRPLUS' in self.__rpc_data:
> - self.__print_rpc_op_stats('READDIRPLUS', sample_time)
> + self.__print_rpc_op_stats('READDIRPLUS', sample_time, use_mb)
> self.__print_dir_cache_stats(sample_time)
> elif which == 3:
> - self.__print_rpc_op_stats('READ', sample_time)
> - self.__print_rpc_op_stats('WRITE', sample_time)
> + self.__print_rpc_op_stats('READ', sample_time, use_mb)
> + self.__print_rpc_op_stats('WRITE', sample_time, use_mb)
> self.__print_page_stats(sample_time)
>
> sys.stdout.flush()
> @@ -500,7 +512,7 @@ def print_iostat_summary(old, new, devices, time, options):
>
> count = 1
> for device in devices:
> - display_stats[device].display_iostats(time, options.which)
> + display_stats[device].display_iostats(time, options)
>
> count += 1
> if (count > options.list):
> @@ -585,6 +597,11 @@ client are listed.
> type="int",
> dest="list",
> help="only print stats for first LIST mount points")
> + displaygroup.add_option('-m', '--megabytes',
> + action="store_true",
> + dest="megabytes",
> + default=False,
> + help="display throughput in megabytes per second (MB/s) instead of kilobytes per second (kB/s)")
> parser.add_option_group(displaygroup)
>
> (options, args) = parser.parse_args(sys.argv)
> diff --git a/tools/nfs-iostat/nfsiostat.man b/tools/nfs-iostat/nfsiostat.man
> index 104c7ab4..4f24318d 100644
> --- a/tools/nfs-iostat/nfsiostat.man
> +++ b/tools/nfs-iostat/nfsiostat.man
> @@ -56,16 +56,16 @@ This is the length of the backlog queue.
> .RE
> .RE
> .RS 8
> -- \fBkB/s\fR
> +- \fBkB/s (MB/s)\fR
> .RS
> -This is the number of kB written/read per second.
> +This is the number of kB (or MB) written/read per second.
> .RE
> .RE
> .RE
> .RS 8
> -- \fBkB/op\fR
> +- \fBkB/op (MB/op)\fR
> .RS
> -This is the number of kB written/read per each operation.
> +This is the number of kB (or MB) written/read per each operation.
> .RE
> .RE
> .RE
> @@ -122,6 +122,9 @@ shows help message and exit
> .B \-l LIST or " \-\-list=LIST
> only print stats for first LIST mount points
> .TP
> +.B \-m or " \-\-megabytes
> +display throughput in megabytes per second
> +.TP
> .B \-p " or " \-\-page
> displays statistics related to the page cache
> .TP
prev parent reply other threads:[~2026-05-06 20:33 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 20:56 [PATCH] nfs-utils: add option to display throughput in MB/s Tigran Mkrtchyan
2026-05-06 20:33 ` Steve Dickson [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=32b6dcdc-c7af-4e2e-8639-06e590f82599@redhat.com \
--to=steved@redhat.com \
--cc=linux-nfs@vger.kernel.org \
--cc=tigran.mkrtchyan@desy.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox