New BSD License. http://en.wikipedia.org/wiki/BSD_licenses
-O6 -DNDEBUG -fomit-frame-pointer
-fexpensive-optimizations -fschedule-insns2 -finline-functions
-funroll-loops -fPIC -march=native
gettimeofday()
システムコールを用いた.
そのコードは
StopWatch.hh
である.
std::map
生成とコピー (perf_map_copy.cpp
)
繰り返しの数 = 100000.結果の経過時間はこの平均を示す.(10万回試してその平均時間を示した.)
Key の数 | |
50 keys | 14 micro seconds (1.4x10-6 sec) |
100 keys | 33 micro seconds (3.3x10-6 sec) |
コメント: 私は数ミリセカンドかかる関数の結果の報告に map を使っている.この計測によって結果の報告のオーバーヘッドは無視できるものとわかった.最初に心配したのは,結果の報告の部分が,実際に必要な計算に対して重大な割合を占めていたらどうしようというものであった.実はこの関数を python のインタープリタに bind して python から 10万回 呼び出してみたが,bind によってもう一度 map (python dict) を作成する時間のオーバーヘッドのみであることがわかった.(ここでは,boost::python 1.48 を使った.)
perf_nth_element.cpp
)
繰り返しの数 = 100000. (それぞれの操作を 100000 回繰り返したものの経過時間を示す.)
Array の大きさ(要素数) | sort | nth_element |
4096 | 4.20 sec | 1.18 sec |
8192 | 8.98 sec | 2.30 sec |
16384 | 19.2 sec | 4.59 sec |
32768 | 40.9 sec | 9.32 sec |
65536 | 88.1 sec | 18.7 sec |
コメント: median の値を小さな array に対して求める必要があった.nth_element の実装は予想された通り,sort したものより高速であることが確認された.
set
と hash_set
の性能比較. (perf_set_hash_set.cpp
)
繰り返しの数 = 1000000. (百万回の insert を行い,続いて継いで百万回の find, そして最後に継いで百万回の remove を行なった.経過時間を示す.
Method | set | hash_set |
insert() | 7.31 sec | 922 millisec |
find() | 4.95 sec | 255 millisec |
erase() | 2.12 sec | 301 millisec |
コメント: コードの入力のシーケンスに注意して欲しい.これらのクラスのメソッドの性能は入力のシーケンスに依存する可能性がある.ここで示したものは連続したシーケンスで人工的である.もし特定のパターンが入力されることがわかっている場合には,その入力でテストするべきである.ここでの結果は set の方が常に遅いことが示されている.しかし,私の好みは遅くても setである.なぜなら,入力が任意の場合,どんな hash 関数でも最悪の振舞いが表れる場合があるためである.たとえ,randomize なものを使うことができても,時に最悪のケースを顧客がみつけて文句を言う場合がある.我々の顧客はそのようなケースをみつけることが上手い.set の性能がクリティカルでない場合,より安定した性能を示す set を使う方が私は多い.驚きが少ないし,hash の最悪のケースを修正することはできても,いつまた顧客が他の最悪のケースをみつけてくるかもしれないからである.同じようなバグが何回も出てくるのは顧客との関係にはあまりよくないことである.