[VB.NET] システムクロックの精度

2016年2月22日

 たとえば、以下のようなプログラムを実行します。

Sub Main()

    Dim sw = New Stopwatch
    sw.Start()
    For i = 1 To 1000
        ' 1ms 待ち
        Threading.Thread.Sleep(1)
    Next
    sw.Stop()

    Console.WriteLine("経過 {0} ms", sw.Elapsed.TotalMilliseconds)

End Sub

 1ms 待ちを 1000 回繰り返しているだけなので、期待値は 1秒(1000ms) ですがそうはなりません。
 実際に実行すると、以下のように 15 秒前後かかります。

C> ConsoleApplication1
経過 15076.4839 ms

 これは、システムクロックの精度がデフォルトでは 15.625 ms であるためです。
 つまり、1ms 止めているつもりが、システムクロックの精度が 15.625 ms であるため、15ms 前後止まっているということです。

 現在のシステムクロックの精度は Sysinternal ツールの Clockres を使うことで確認できます
 https://technet.microsoft.com/ja-jp/sysinternals/bb897568.aspx

C>clockres

ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com

Maximum timer interval: 15.625 ms
Minimum timer interval: 0.500 ms
Current timer interval: 15.625 ms

 ということで、このシステムクロックの精度を15.625 ms から 1ms に変えてやれば、冒頭のプログラムは期待通りに動いてくれそうです。

 ということで、以下のプログラムによって、システムクロックの精度を 1ms に変えます。

Private Declare Sub NtSetTimerResolution Lib "ntdll.dll" Alias "NtSetTimerResolution" _
(
    ByVal desiredResolution As UInt32,
    ByVal setResolution As Boolean,
    ByRef CurrentResolution As UInt32
)


Sub Main()

    ' 1ms : 100ns (NtSetTimerResolution の設定の分解能が 100ns であるため)
    Const RATIO = 10 * 1000

    ' 変更値 (1ms) 
    Dim modifyMilliseconds As Double = 1

    ' 変更
    Dim currentMilliseconds = 0
    NtSetTimerResolution(CInt(modifyMilliseconds * RATIO), True, currentMilliseconds)

    ' 結果
    Console.WriteLine("Current timer interval: {0}ms", currentMilliseconds / RATIO)
    Console.Read()

End Sub

 プログラムが終了してしまうとデフォルト値に戻ってしまうので、何かキーを入力しないと、プログラムの終了をしないようにしています。

 上記のプログラムを実行中に、冒頭のプログラムを実行してみます。
 その結果は以下。

C> clockres

ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com

Maximum timer interval: 15.625 ms
Minimum timer interval: 0.500 ms
Current timer interval: 1.000 ms

C> ConsoleApplication1
経過 1718.0604 ms

 結果は約 1.7 秒と、まだ理論値からは外れているものの、デフォルトのシステムクロック精度のときの約 15 秒よりも大幅に理論値に近くなりました。

 このように、ms 単位の待ち時間やタイマー割り込みを使用する場合は、システムクロックの精度を気にする必要があります。
 加えて、システムクロックの精度の変更は、そのアプリケーションだけでなく Windows 全体に影響が及ぶので、軽率に変更するべきではない点にも注意が必要です。






カテゴリー: OS, Program, VB.NET, Windows

Follow comments via the RSS Feed | Leave a comment | Trackback URL

コメントを投稿する

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


«   »
 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org