例を挙げましょう:
$ timeout 1 yes "GNU" > file1
$ wc -l file1
11504640 file1
$ for ((sec0=`date +%S`;sec<=$(($sec0+5));sec=`date +%S`)); do echo "GNU" >> file2; done
$ wc -l file2
1953 file2
ここでは、コマンドyes
が11504640
1 1953
秒で行を書き込むのに対してfor
、bash とを使用して5秒で行のみを書き込むことができますecho
。
コメントで示唆されているように、それをより効率的にするためのさまざまなトリックがありますが、どれも速度に匹敵するものはありませんyes
:
$ ( while :; do echo "GNU" >> file3; done) & pid=$! ; sleep 1 ; kill $pid
[1] 3054
$ wc -l file3
19596 file3
$ timeout 1 bash -c 'while true; do echo "GNU" >> file4; done'
$ wc -l file4
18912 file4
これらは、1秒間に最大2万行を書き込むことができます。さらに、次のように改善できます。
$ timeout 1 bash -c 'while true; do echo "GNU"; done >> file5'
$ wc -l file5
34517 file5
$ ( while :; do echo "GNU"; done >> file6 ) & pid=$! ; sleep 1 ; kill $pid
[1] 5690
$ wc -l file6
40961 file6
これにより、1秒で最大4万行になります。良いが、それでもyes
1秒間に約1,100万行を書き込むことができるのはまだまだ遠いです!
それでは、ファイルへの書き込みはどのyes
ように高速ですか?
date
やや重いですが、シェルはecho
ループの反復ごとに出力ストリームを再度開く必要があります。最初の例では、単一の出力リダイレクトを使用した単一のコマンド呼び出しのみがあり、コマンドは非常に軽量です。2つは決して比較できません。
date
ことは重いかもしれません、私の質問の編集を参照してください。
timeout 1 $(while true; do echo "GNU">>file2; done;)
使用するために間違った方法であるtimeout
ため、timeout
コマンド置換が終了すると、コマンドのみを起動します。を使用しtimeout 1 sh -c 'while true; do echo "GNU">>file2; done'
ます。
write(2)
最初の例(date
ファイルに出力されるすべての行を実行して待機する)で、他のsyscallのボート負荷、シェルオーバーヘッド、またはプロセスの作成ではなく、システムコールのみにCPU時間を費やします。大量のRAMを搭載した最新のシステムでは、1秒の書き込みでディスクI / O(CPU /メモリではなく)のボトルネックになります。長く実行できる場合、差は小さくなります。(使用するbashの実装の悪さ、およびCPUとディスクの相対速度によっては、bashでディスクI / Oを飽和させることさえできない場合があります)。