localhost とある host との間の伝送効率と遅延を ping を用いて測定した.ping を使うアイデアは,pingでネットワークの速度を調査する - @IT にて示されている.以下の bash プログラムでは,大きさの異なるパケットを指定された host に対して ping し,往復にかかった時間を測る.これらパケットサイズと往復にかかった時間との関係に一次関数を仮定し,フィッティングして得た傾きと切片をそれぞれ伝送効率と遅延とする.最小二乗フィッティングには gnuplot を使った.その後一定時間の休みを挟み,測定を繰り返す.各繰り返しでは,その繰り返しで測定した結果だけではなく,それまでに測定した結果をすべてフィッティング対象にする.
#!/bin/bash
readonly counts=1
readonly maxsize=1472
readonly sleepsecond=600
remote="${1}"
shift
if [ "x${remote}" = 'x' ]; then
echo "Usage: ${0} remote_host" >&2
exit 1
fi
resultfile=$( mktemp )
trap "rm -r ${resultfile}" EXIT
countsprev=0
for (( i=1;; i++ ))
do
s=${maxsize}
while true
do
if [ ! ${s} -gt 0 ]; then
break
fi
unset pattern
while [ "x${pattern}" = 'x' ]
do
pattern=$(hexdump -e '/2 "%02x"' -n "${s}" /dev/urandom)
done
ping -c "${counts}" -p "${pattern}" -s "${s}" "${remote}" \
| awk '$2 == "bytes" && $3 == "from" && $4 = "'"${remote}"':" { print $1, $7 }' \
| while read size time
do
if [ "x${size}" = 'x' ]; then
continue
fi
if [ "x${time}" = 'x' ]; then
exit 128
fi
time_ms="${time#time=}"
echo "${size} ${time_ms}" >> "${resultfile}"
done
if [ $? -eq 128 ]; then
break
fi
if [ $? -ne 0 ]; then
echo "Failed: ping -c ${counts} -p ${pattern} -s ${s} ${remote}" >&2
fi
s=$( echo "scale=0; ${s}/1.41421356" | bc )
done
echo "data [${i}]:"
tail -$( expr $( wc -l < "${resultfile}" ) - ${countsprev} ) ${resultfile}
countsprev=$( wc -l < "${resultfile}" )
echo "data [${i}] end: ${countsprev}"
gnuplot -persist <(echo \
"fit a*x+b '${resultfile}' using 1:2 via a, b
print \"transport rate: \", 1000/a/1024/1024*2, \" Mbytes/s\"
print \" overhead: \", b, \" ms\"
plot a*x+b, '${resultfile}' using 1:2") 2>&1 \
| sed -n '/^After [1-9][0-9]* iterations the fit converged\. *$/,$ p'
sleep "${sleepsecond}"
done