[bash]シェルスクリプトのループ内でのリダイレクト

シェルスクリプトのループはあまり速くない。
なので、できるだけ速くさせるためにはリダイレクトの位置に気をつけたい。

これは遅い
for i in $( seq 100000 )
do
  echo $i >>loop.dat
done
手元の環境で1.027秒かかった。
これはどうだろうか。
for i in $( seq 100000 )
do
  echo $i
done >>loop.dat
先ほどと同じ環境で0.609秒となった。40%もの改善だ。
あらかじめ、execコマンドで標準出力の向き先を変えておくとどうだろうか?
exec 1>loop.dat
for i in $( seq 100000 )
do
  echo $i
done
こちらは0.610秒。ループ自体をリダイレクトするのとほぼ同じ結果となった。
まあ、今回のケースではループする必要なんてないんですが。。。
seq 100000 >loop.dat
#ちなみにこれは0.011秒で終わる!

というわけで、今回の教訓はシェルスクリプトでループは邪道。
じゃなくって、ループの中でリダイレクトするなってことでした。

[linux]システムコールの一覧

Linuxのシステムコールの一覧ってどこかにないかなと思ったんですが、man syscallsで見られるんですね。

$ man syscalls

同じような感じでCの標準ライブラリ関数の一覧って、見られないのかな。。。

[bash]ビルトインコマンドのヘルプ

プロセスの消費リソース表示 その1で2種類のtimeコマンドについて書いたけど、シェルのビルトインコマンドがどのようなオプションを受け付けるのかあまりよくわかってなかった。
manで調べると外部コマンドのtimeの情報が出てくる。

$ man time

調べてみたところbashのビルトインコマンドの説明はhelpで出てくるらしい。
例えばtimeの説明は以下のようになる。

$ help time
time: time [-p] pipeline
    Report time consumed by pipeline's execution.
    
    Execute PIPELINE and print a summary of the real time, user CPU time,
    and system CPU time spent executing PIPELINE when it terminates.
    
    Options:
      -p        print the timing summary in the portable Posix format
    
    The value of the TIMEFORMAT variable is used as the output format.
    
    Exit Status:
    The return status is the return status of PIPELINE.
times: times
    Display process times.
    
    Prints the accumulated user and system times for the shell and all of its
    child processes.
    
    Exit Status:
    Always succeeds.

これを見るとtimesというビルトインコマンドもあることがわかる。
面白いのはifやforといったシェルの制御構文もhelpで見られるところ。

$ help if
$ help for

シェルスクリプトを書いていて、ちょっと書き方を参照したいときにいちいちweb等で調べなくていいので便利。

[linux]プロセスの消費リソース表示 その2

その1では紹介したtimeコマンドの他にperfコマンドを使う方法がある。
※perfはシステムにデフォルトでは入っていないかもしれない。

perfはいくつかのサブコマンドから成り立っているけど、起動したプロセスの情報を単純に取得するにはstatを使うといい。

$ perf stat sort -r foo.txt

 Performance counter stats for 'sort -r foo.txt':

          1.880898 task-clock                #    0.569 CPUs utilized
               104 context-switches          #    0.055 M/sec
                 1 cpu-migrations            #    0.532 K/sec
               284 page-faults               #    0.151 M/sec
         2,905,110 cycles                    #    1.545 GHz
    stalled-cycles-frontend 
    stalled-cycles-backend  
         2,624,591 instructions              #    0.90  insns per cycle
           559,006 branches                  #  297.202 M/sec
            17,821 branch-misses             #    3.19% of all branches

       0.003305801 seconds time elapsed

また、下記のように-rオプションで実行回数を指定することもできる。

$ perf stat -r 5 sleep 1
 Performance counter stats for 'sleep 1' (5 runs):

          1.657008 task-clock                #    0.002 CPUs utilized            ( +-  3.25% )
                 2 context-switches          #    0.001 M/sec                    ( +- 20.79% )
                 0 cpu-migrations            #    0.121 K/sec                    ( +-100.00% )
               199 page-faults               #    0.120 M/sec
         1,338,609 cycles                    #    0.808 GHz                      ( +-  1.99% )
    stalled-cycles-frontend 
    stalled-cycles-backend  
         1,150,478 instructions              #    0.86  insns per cycle          ( +-  0.37% )
           233,825 branches                  #  141.113 M/sec                    ( +-  0.36% )
             9,804 branch-misses             #    4.19% of all branches          ( +-  1.32% )

       1.003059076 seconds time elapsed                                          ( +-  0.03% )