6

1 ミリ秒を超える精度で時間を報告するタイム サービスを実装しようとしています。簡単な解決策は、最初の測定を行い、StopWatch を使用してそれにデルタを追加することだと思いました。問題は、この方法が壁時間から非常に速く発散しているように見えることです。たとえば、次のコードはウォール タイムと高解像度クロックの間の差異を測定しようとします。

public static void Main(string[] args)
{
    System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
    DateTime baseDateTime = DateTime.UtcNow;
    s.Start();
    long counter = 0;
    while(true)
    {
        DateTime utcnow = DateTime.UtcNow;
        DateTime hpcutcnow = baseDateTime + s.Elapsed;
        Console.WriteLine(String.Format("{0}) DT:{1} HP:{2} DIFF:{3}", 
            ++counter, utcnow, hpcutcnow, utcnow - hpcutcnow));
        Thread.Sleep(1000);
    }
}

かなり最近のサーバー ハードウェアでは、約 2 ミリ秒/分の速度で発散しています。

私が認識していないウィンドウに、より正確になる別の時間機能はありますか? そうでない場合、高解像度のクロックまたはサードパーティのライブラリを作成するためのより良い方法はありますか?

4

2 に答える 2

11

正確な時計を手に入れるのは難しい。ストップウォッチは非常に高い解像度を持っていますが、正確ではなく、チップセットの信号から周波数を導き出しています。これは、典型的な電子部品の公差で動作します。ハードウェア ビジネスにおける熾烈な競争により、安定した周波数が保証された高価な水晶発振器が先制されました。

DateTime.UtcNow もそれほど正確ではありませんが、助けになります。Windows は定期的にタイム サービスにアクセスします。既定のサービスは time.windows.com で、高品質のクロックの更新を取得します。そして、それを使用してマシンのクロックを再調整し、小さな調整を挿入して、クロックが追いつくか遅くなるようにします。

ミリ秒まで正確にするには、もっと大きなトリックがたくさん必要です。そのような保証を得ることができるのは、カーネル モードで実行され、割り込み優先度で実行されるコードに対してのみ得られるため、他のコードによってプリエンプトされることはなく、そのコードとデータ ページがページ ロックされているため、ページ フォールトにヒットすることはありません。 . 商用ソリューションでは、GPS ラジオを使用して GPS 衛星のクロック信号を読み取り、オーブンで動作する発振器によってバックアップされて温度安定性を提供します。このようなクロックを読み取るのは難しい問題です。サブミリ秒のクロック ソースを使用するプログラムが、時刻を取得したときにオペレーティング システムによってプリエンプトされ、次の時点まで実行を再開できない場合、サブミリ秒のクロック ソースはあまり役に立ちません。約 45 ミリ秒後。またはさらに悪い。

DateTime.UtcNow は 15.625 ミリ秒の精度で、タイム サービスの更新のおかげで非常に長期間安定しています。それよりも低くしてもあまり意味がありません。ユーザー モードでそれを利用するために必要な実行保証を得ることができません。

于 2013-11-01T23:19:36.860 に答える
4

Windows 8/Server 2012 では、特に高解像度のタイムスタンプを取得するための新しい API、GetSystemTimePreciseAsFileTime API が追加されたようです。これをいじる機会はありませんでしたが、有望に見えます。

于 2014-04-28T21:05:02.880 に答える