タイマーを実装していますが、50 ミリ秒ごとに実行する必要があり、分解能を 1 ミリ秒以下にしたいと考えています。私は次の 2 つの記事を読むことから始めました。
http://www.codeproject.com/Articles/1236/Timers-Tutorial
http://www.virtualdub.org/blog/pivot/entry.php?id=272
奇妙なことに、それらは互いに矛盾しているように見えます。キュー タイマーは高解像度に適していると言う人もいれば、Windows 7 システムで約 15 ミリ秒の解像度を示す投稿もあります (私のアプリケーションには十分ではありません)。
そこで、自分のシステム (Win7 64bit i7-4770 CPU @3.4 Ghz) でテストを実行しました。私は50ミリ秒の期間で開始し、これが私が見ているものです(左が開始からの時間、右が実行間のギャップ、すべてミリ秒):
150 50.00
200 50.01
250 50.00
...
450 49.93
500 50.00
550 50.03
...
2250 50.10
2300 50.01
最大エラーは約 100 us であり、平均エラーはおそらく約 30 us 程度であることがわかります。これは私をかなり幸せにします。
そこで、どの時点で信頼性が低くなるかを確認するために、期間を落とし始めました。期間を 5 ミリ秒以下に短縮すると、悪い結果が見られるようになりました。
周期が 5 ミリ秒の場合、数秒ごとに 3 ミリ秒から 6 ミリ秒の間で周期がジャンプすることは珍しくありません。周期を 1 ミリ秒に減らすと、5 ~ 10 ~ 40 ミリ秒の周期が見られます。40ミリ秒までのジャンプは、画面に何かを印刷しているという事実が原因である可能性があると思いますが、わかりません。
これは私のタイマーコールバックコードです:
VOID CALLBACK timer_execute(PVOID p_parameter,
BOOLEAN p_timer_or_wait_fired)
{
LARGE_INTEGER l_now_tick;
QueryPerformanceCounter(&l_now_tick);
double now = ((l_now_tick.QuadPart - d_start.QuadPart) * 1000000) / d_frequency.QuadPart;
double us = ((l_now_tick.QuadPart - d_last_tick.QuadPart) * 1000000) / d_frequency.QuadPart;
//printf("\n%.0f\t%.2f", now / 1000.0f, ms / 1000.0f);
if (us > 2000 ||
us < 100)
{
printf("\n%.2f", us / 1000.0f);
}
d_last_tick = l_now_tick;
}
とにかく、100hz 以下で実行している限り、キュー タイマーは非常に優れたツールのように思えます。私がリンクした 2 番目の記事に掲載された悪い結果 (15 ミリ秒程度の精度) は、CPU が遅いためか、構成が異なるためでしょうか?
複数のマシンでこの種のパフォーマンスを期待できるかどうか疑問に思っています (すべて 64 ビット Win7 を実行しているマシンと同じか、それよりも高速です)。また、期間が経過する前にコールバックが終了しない場合、OS がそこに別のスレッドを配置することに気付きました。これは明らかかもしれませんが、どのドキュメントでも目立たず、クライアント コードに重大な影響を及ぼします。