今回は速度計測ネタです。いわゆるベンチマークというやつです。ベンチマークテストにはDhrystone(ドライストーン)などの有名なものもありますが、UNIXコマンドにはtimeという便利なものがあります。今回は、このコマンドを使ってみましょう。
今回もサンプルプログラムなどはデスクトップのsampleディレクトリに入れておくことにします。
使っているシェルを確認
timeコマンドは以後に指定されたプログラムの開始から終了までにかかった時間を計測し結果を出力してくれます。使い方は割と簡単です。
といきたいところですが、ここで注意事項があります。ここではtimeコマンドはzshではなくbashのシェル上で動かすことにします。また、/usr/bin/timeのtimeとは別です。要するに面倒な(?)ことに
bashの内部コマンド time
zshの内部コマンド time
/usr/bin/time
と3つあるわけです。それぞれ出力結果や使用できるオプションが異なります。最初にbashの内部コマンドのtimeを使うことにします。
macOSの場合はデフォルトではzshなのでターミナルでbashに切り替えてください。
バージョンは関係ないのでHomebrewでbash 4を入れている場合は、それを使ってください。macOSでbashに切り替えるには以下のようにbashと入力するだけです。
bash
UbuntuなどLinux系の場合は基本的にbashがデフォルトになっているので、そのままtimeコマンドを実行するだけです。もし、デフォルトのシェルがbashではない場合はmacOSと同様にbashと入力すれば切り替わります。
今使っているシェルがわからない場合は以下のようにコマンドを入力してください。
echo $0
ちなみに使えるシェルを確認するには以下のように入力します。
cat /etc/shells
timeコマンドのオプション
timeコマンドについてはman timeとすると説明がでてきます。ただし、表示されるのは/usr/bin/timeのものです。このため、bash, zshの内部コマンドのtimeでは使えないオプションもあります。例えば/usr/bin/timeでは-oで結果をファイルに出力できますが、bashのtimeコマンドでは使用できません。
timeコマンドで速度計測
少し長くなりましたがtimeコマンドを使って実行にかかった時間を計測してみましょう。まず、簡単なところでecho 123の速度を計測します。以下のようにコマンドを入力します。
time echo 123
実行するとかかった時間が表示されます。realはコマンド実行にかかった時間、userはユーザーCPU時間、sysはシステムCPU時間になります。
echoでは時間が短すぎるので、もう少し時間のかかるコマンドを実行してみましょう。sleep 3なら3秒時間がかかるはずなので、実行時間がどうなるかやってみます。1回ではなく3回実行した結果は以下の図のようになります。いろいろな関係できっかり3秒にはなりません。
time sleep 3
今度は時間のかかるfindコマンドを実行してみましょう。ユーザーディレクトリ以下から、なさそうなファイルの拡張子を指定してみます。
time find ~/ -name *.mzt
ファイルが多いとそれなりに時間がかかりますが、ファイルがほぼない場合はすぐに終わります。また、検索対象デバイスがハードディスクなのかSSDなのかによっても異なります。
という事で、今度は同じファイルを外付けSSDと内部のSSDと、SDカードからコピーして時間を比較してみましょう。
コピーはcpコマンドを使います。それぞれ計測した結果は以下のようになります。SDカードやSSDのファイルパスは環境によって異なるので、以下のコマンドを使って計測したい場合は環境に合わせて変更してください。
・内蔵SSDから内蔵SSD
time cp 0.MTS 1.MTS
・外付けSSDから内蔵SSD
time cp /Volumes/photoMax15/0.MTS ~/Desktop/Sample/0.MTS
・SDカードから内蔵SSD
time cp /Volumes/CAM_SD/0.MTS ~/Desktop/sample/0.MTS
自作のシェルスクリプトの処理速度を計測
timeコマンドの便利なところは自作のシェルスクリプトの速度も計測できる点です。
まず、簡単なところで繰り返し処理を計測してみましょう。bashの繰り返しはforですが、いくつか書き方があります。そこで、書き方によって、どのくらい速度が異なるのかを計測してみます。基本的に処理速度のネックとなるのは繰り返し部分です。
なお、以下で実行するシェルスクリプトは0から999まで画面に数値を表示するだけのものです。
#!/bin/bash
for ((i=0; i<1000; i++)); do
echo $i
done
▪2.sh
#!/bin/bash
for i in {0..999}; do
echo $i
done
▪3.sh
#!/bin/bash
array=({0..999})
for i in ${array[@]}; do
echo $i
done
さすがに近年のマシンは高速なので、もう少し回数を多くするか負荷が高いものにしないといけなかったかもしれません。幸い(?)15年前のMacPro (2009年) のマシンがあったので1.sh,2.sh,3.shを計測してみました。今となっては小型のラズベリーパイ5の方が高速でした。これも時代の流れですが、ウン十万円もしたマシンが15年も経過すると数千円のものにもかなわないのは、う〜んと天を仰いでしまいます。
その他のシェルのtime
最後に他のシェルでtimeコマンドを実行してみましょう。ここではmacOSでシェルを切り替えて実行してみます。
sh
echo $0
time sleep 3
csh
echo $0
time sleep 3
tcsh
echo $0
time sleep 3
ksh
echo $0
time sleep 3
zsh
echo $0
time sleep 3
次にシェルではなく/usr/bin/timeで実行してみます。
/usr/bin/time sleep 3
せっかくなので最後にPowerShell Coreでの計測方法も載せておきます。
PowerShellではMeasure-Commandを使います。
Measure-Command {
Write-Host 123
}
ちなみに以下のように1行にまとめることもできます。ここでは1行で実行した結果を示します。
Measure-Command { Write-Host 123 }
いろいろな情報が表示されますが、秒数だけ分かればいいのであれば以下のようになります。
(Measure-Command { Start-Sleep -Seconds 3 }).Seconds
Ticktimeなら以下のようになります。他の値も同様に指定すれば必要な項目だけを表示させることができます。
(Measure-Command { Start-Sleep -Seconds 3 }).Ticks
速度計測といえばベンチマークテストを行うプログラム(Unix Bench等)もありますが、これはまたの機会にでも。 それでは、また次回。
著者 仲村次郎
いろいろな事に手を出してみたものの結局身につかず、とりあえず目的の事ができればいいんじゃないかみたいな感じで生きております。