NFS Read/Write Histogram Calculation
This example shows a simple shellscript that uses tethereal to calculate
NFS Read/Write I/O completion time histograms.
It supports both version 2 and version 3 of NFS.
The script will output the number of NFS calls that completed within
each of the 5 ms intervals starting at 0 to 100ms and one last datapoint
for all calls that took more than 100ms to complete.
One such table will be printed for RREAD and one for WRITE.
Note that the -z rpc,rtt,... feature will only calculate the statistics
based on those calls where both the REQUEST and the matching REPLY is
in the capture file. REPLY packets with no matching REQUEST packet will
be ignored.
Also note that if there are retransmission of REPLY packets, each REPLY
packet will be considered unique and all of them will be used for the
calculation.
Example output:
READ
5
7
8
...
2
WRITE
...
This tells us that 5 NFS READ commands completed within 0-5ms,
7 READs completed within 5-10ms, etc
and that 2 READs took >100ms to complete.
Similar for WRITEs.
#!/bin/sh
if [ $# != "2" ]; then
echo "Usage: nfsrwhist.sh VERSION FILENAME"
echo " create read/write execution time for NFS version VERSION"
echo
echo "Example: nfsrwhist.sh 3 capture.cap"
exit
fi
# -R "not frame" is a trick to prevent tethereal for printing any
# packet summary lines. "not frame" is a read filter which will match
# no packets at all and thus tethereal will not print any packet summaries.
#
# the -z io,... statistics calculations still works though since it use
# its own packet filtering and ignores the read-filter.
tethereal -R "not frame" -r $2 \
-z "rpc,rtt,100003,$1,rpc.time>0.100" \
-z "rpc,rtt,100003,$1,rpc.time>0.095 && rpc.time<=0.100" \
-z "rpc,rtt,100003,$1,rpc.time>0.090 && rpc.time<=0.095" \
-z "rpc,rtt,100003,$1,rpc.time>0.085 && rpc.time<=0.090" \
-z "rpc,rtt,100003,$1,rpc.time>0.080 && rpc.time<=0.085" \
-z "rpc,rtt,100003,$1,rpc.time>0.075 && rpc.time<=0.080" \
-z "rpc,rtt,100003,$1,rpc.time>0.070 && rpc.time<=0.075" \
-z "rpc,rtt,100003,$1,rpc.time>0.065 && rpc.time<=0.070" \
-z "rpc,rtt,100003,$1,rpc.time>0.060 && rpc.time<=0.065" \
-z "rpc,rtt,100003,$1,rpc.time>0.055 && rpc.time<=0.060" \
-z "rpc,rtt,100003,$1,rpc.time>0.050 && rpc.time<=0.055" \
-z "rpc,rtt,100003,$1,rpc.time>0.045 && rpc.time<=0.050" \
-z "rpc,rtt,100003,$1,rpc.time>0.040 && rpc.time<=0.045" \
-z "rpc,rtt,100003,$1,rpc.time>0.035 && rpc.time<=0.040" \
-z "rpc,rtt,100003,$1,rpc.time>0.030 && rpc.time<=0.035" \
-z "rpc,rtt,100003,$1,rpc.time>0.025 && rpc.time<=0.030" \
-z "rpc,rtt,100003,$1,rpc.time>0.020 && rpc.time<=0.025" \
-z "rpc,rtt,100003,$1,rpc.time>0.015 && rpc.time<=0.020" \
-z "rpc,rtt,100003,$1,rpc.time>0.010 && rpc.time<=0.015" \
-z "rpc,rtt,100003,$1,rpc.time>0.005 && rpc.time<=0.010" \
-z "rpc,rtt,100003,$1,rpc.time<=0.005" >/tmp/nfsrwhist.$$
echo -n "READ: "
cat /tmp/nfsrwhist.$$ | grep "^READ " | sed -e "s/^READ *//g" -e "s/ .*$//"
echo
echo -n "WRITE: "
cat /tmp/nfsrwhist.$$ | grep "^WRITE " | sed -e "s/^WRITE *//g" -e "s/ .*$//"
echo
rm /tmp/nfsrwhist.$$