[C]LinuxでCプログラムの処理時間を計測する方法いくつか その1

LinuxのCプログラムで処理時間の計測をする場合にはいくつかの方法が考えられるけど、それぞれの違いがあまりよくわかってなかったので、どのような長所、短所があるか調べてみた。

大きく分けて、システム時刻を取得する方法とプロセスの消費CPU時間を取得する方法がある。
何を計測するのかによって、どちらを使うか決める必要があるだろう。

まずはANSI Cで決められている関数を使う方法。移植性は最も高い。

[time関数]
#include <time.h>
time_t time(time_t *t);

time関数は現在のシステム時刻を返す。
ただし、秒精度までしか求められない上に計測中にシステム時刻が変更された場合にはズレが生じてしまう。

例:
    time_t start;
    time_t end;
    long elapsed;

    time(&start);
    // 計測したい処理...
    time(&end);

    elapsed = (long)difftime(end, start);
移植性を考えれば、time_t型は直接引き算をするのではなく、difftimeを使ったほうがいいだろう。

[clock関数]
#include <time.h>
clock_t clock(void);

こちらはプロセスが使用したCPU時間を返す。
戻り値をCLOCKS_PER_SECで割れば、秒数に変換することもできる。
※CLOCKS_PER_SECはプロセッサの実際のクロック数の精度ではなく、C89,C99では1000000であることが要求されている。

例:
    clock_t start;
    clock_t end;
    long elapsed;
    long elapsedsec;

    start = clock();
    // 計測したい処理...
    end = clock();

    elapsed = (long)(end - start);
    elapsedsec = elapsed / CLOCKS_PER_SEC;

ただし、time関数と違い、sleep等でCPU時間を消費しない待機はカウントされないため、注意しよう。
※time_tとclock_tはlongとして定義されている処理系が多いけど、必ずしもそうではないので注意しよう。

DOT言語

クラス図などを書くときにはUMLのモデリングツールや、ソースコードからの自動生成ツールを使うことが多いと思うけど、DOT言語というのを使うとクラス図のようなグラフ図をテキストから生成できる。

Graphviz Documentation
http://www.graphviz.org/Documentation.php
DOTユーザーズガイド日本語訳
http://cbrc3.cbrc.jp/~tominaga/translations/index.html#dot

Doxygenでも図の生成にdotを使用している。
http://www.doxygen.jp/diagrams.html

例えば、以下のようなDOT言語のテキストをsample.dotという名前のファイルに保存して
digraph sample {
    node [ shape = box ];
    edge [ dir = back, arrowtail = onormal, arrowsize = 1.5 ];

    Collection [ label = "<<interface>>\nCollection" ];
    Set        [ label = "<<interface>>\nSet" ];
    SortedSet  [ label = "<<interface>>\nSortedSet" ];
    List       [ label = "<<interface>>\nList" ];
    Queue      [ label = "<<interface>>\nQueue" ];
    Map        [ label = "<<interface>>\nMap" ];
    SortedMap  [ label = "<<interface>>\nSortedMap" ];

    Collection -> Set -> SortedSet;
    Collection -> List;
    Collection -> Queue;
    Map -> SortedMap;

    { rank = same; Set; Map; }
}

dotコマンドに画像を生成させる。
この場合はGIF形式を生成しているけど、PNG,JPEG等、様々な形式に対応している。

$ dot -Tgif sample.dot -o sample.gif

すると以下のような画像が生成される。



ソースコード管理システムでのバージョン管理とも相性良さそうだし、ちょっとした図を書くときなんかに使えるんじゃないだろうか。

[awk]gawkとmawk

多くのLinuxディストリビューションではデフォルトのawkとしてgawkが採用されているけれども、Debian系ではデフォルトのawkとしてgawkではなく、mawkが採用されているようだ。
mawkってなにものだろうか?

http://invisible-island.net/mawk/

mawkはgawkのような高度な拡張機能は使えないけれども、その分高速に動作することを目標に作られている。
grep,egrep,fgrepみたいなもんか。

もし、awkが意図しているオプションを受け付けなかったりしたら、どのawkを使っているか確認するといい。
また、gawkを使っていてパフォーマンスを上げたい場合はmawkの使用を検討するといいかもしれない。

[Java]equalsメソッド実装時にテストすること

自分で作ったクラスにequalsメソッドを実装した場合、最低限以下の挙動はテストしておく必要がある。
  1. 反射律
    自分自身との同値比較は真となること。
    a.equals(a)は必ずtureになるということ。

  2. 対称律
    同値比較の左辺と右辺を入れ替えても比較結果は変わらないということ。
    a.equals(b)がtrueであれば、b.equals(a)もtrueとなるということ。
    falseの場合も同じ。

  3. 推移律
    a,bの同値比較結果とb,cの同値比較結果が同じであれば、a,cの同値比較結果も同じとなるということ。
    a.equals(b)がtrueでb.equals(c)がtrueであれば、a.equals(c)もtrueとなるということ。
    falseの場合も同じ。
これらについてはJava APIリファレンスのObjectクラスのequalsメソッドの項にも書かれている。

また、一般的にオブジェクトの中身に言及せずに、上記の3条件を満たしていることがオブジェクトの同値性の定義でもあるというところが面白い。