MeteredSectionがCRITICAL_SECTION より速すぎてびっくらこいた。

CriticalSection
CriticalSection End 45676 msec
MeteredSection
MeteredSection End  30577 msec
Press any key to continue

MeteredSectionが15000msec も早いだと。
テストプログラム書いて試してみたら、CRITICAL_SECTION よりMeteredSectionの方が早いのね。
なんでなんだろう、、直感的に CRITICAL_SECTION の方が早い気がするんだが。。。

既存のプログラムを CRITICAL_SECTION から MerteredSectionにするか。。。
それとも、検証の方法が間違っている?

テスト環境

OS Windows XP
CPU Q6600
Memory 2G
コンパイラ VC6++ sp6

プログラムの条件

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

テストプログラムソース一式はこちら。
http://rtilabs.net/files/2009_12_20/CriticalvsMetered.zip

面白かったので、スレッド数を変えながら試した。

スレッドの個数 2←
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 375 msec
MeteredSection End 359 msec

スレッドの個数 4←
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 718 msec
MeteredSection End 625 msec

スレッドの個数 50←
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 11171 msec
MeteredSection End 7719 msec

スレッドの個数 100←
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 22546 msec
MeteredSection End 15485 msec

スレッドの個数 200←
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 45676 msec
MeteredSection End 30577 msec

スレッドの個数 300←
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 68078 msec
MeteredSection End 46437 msec


スレッド数の増大とと主に線形的に時間食べていっているなぁ。。。
後、実行中にCPUをそれほど消費していないんだよなぁ。

共有リソースに対する処理が長すぎるため、ほとんどロック待ちに鳴っているのかなぁ
スレッドの中でやる処理を変化させてみた。

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 10←
スレッドをスタートさせる間隔msec 100

CriticalSection End 21875 msec
MeteredSection End 21875 msec

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 100←
スレッドをスタートさせる間隔msec 100

CriticalSection End 21875 msec
MeteredSection End 21875 msec

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 1000←
スレッドをスタートさせる間隔msec 100

CriticalSection End 21890 msec
MeteredSection End 21891 msec

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000←
スレッドをスタートさせる間隔msec 100

CriticalSection End 45676 msec
MeteredSection End 30577 msec

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 10000
スレッドをスタートさせる間隔msec 100

CriticalSection End 78265 msec
MeteredSection End 55672 msec

排他処理をしている中で行う無駄な処理数を少なくすると、CPUほとんど反応せず。
これまた、予想と違う結果になった。
予想だと、スレッドの仲の排他処理中にやっている処理に時間がかかっていて遅いのだろうと思っていたが、
その排他処理の中でやる無駄な処理を緩和したのにCPUリソースは増えなかった、
逆に、スレッドの排他処理の中でやる無駄な処理を増やした方がCPUが使われることがわかった。

画像は、スレッドの仲の排他処理中にやる無駄な処理を減らした場合のCPU使用率


仕方ないので、次はループ回数を増やして観察してみる。

スレッドの個数 200
スレッドの中でループする回数 10←
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 21875 msec
MeteredSection End 21875 msec

スレッドの個数 200
スレッドの中でループする回数 100←
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 21875 msec
MeteredSection End 21875 msec

スレッドの個数 200
スレッドの中でループする回数 1000←
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 21875 msec
MeteredSection End 21875 msec
この値が10 100 1000でずっと同じということは、やっぱりスレッドの中の無駄な処理が問題をひき起こしていると思うんだけどなぁ。

スレッドの個数 200
スレッドの中でループする回数 10000←
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 45676 msec
MeteredSection End 30577 msec

スレッドの個数 200
スレッドの中でループする回数 50000←
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100

CriticalSection End 227859 msec
MeteredSection End 152383 msec


ダメもとでスレッドをスタートさせる感覚を変化させてみた。

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 0←

CriticalSection End 45765 msec
MeteredSection End 30438 msec

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 100←

CriticalSection End 45676 msec
MeteredSection End 30577 msec

スレッドの個数 200
スレッドの中でループする回数 10000
排他処理をしている中で行う無駄な処理数 5000
スレッドをスタートさせる間隔msec 1000←

CriticalSection End 200125 msec
MeteredSection End 200130 msec


もう何が何だかさっぱりわからねー。
どうして、予想と反する答えばっかりでるんだ。
それと、MerteredSectionってすげー早いぢゃんか。
うーん。検証の方法が悪いんだろうか。ちょっと見直す。

ついでに、MerteredSectionが超早いのはわかったんだけど、google code search で検索しても一軒も引っかからないのは知名度の問題?