70

Environment.TickCount期間の計算に使用しても大丈夫ですか?

int start = Environment.TickCount;
// Do stuff
int duration = Environment.TickCount - start;
Console.WriteLine("That took " + duration " ms");

署名されており、25日後にロールオーバーされるためTickCount(32ビットすべてにヒットするのに50日かかりますが、数学の意味を理解したい場合は、署名されたビットを破棄する必要があります)、リスクが高すぎて役に立たないようです。

DateTime.Now代わりに使用しています。これはこれを行うための最良の方法ですか?

DateTime start = DateTime.Now;
// Do stuff
TimeSpan duration = DateTime.Now - start;
Console.WriteLine("That took " + duration.TotalMilliseconds + " ms");
4

14 に答える 14

103

Environment.TickCountは、 GetTickCount() WinAPI関数に基づいています。ミリ秒単位ですが、実際の精度は約15.6ミリ秒です。したがって、より短い時間間隔を測定することはできません(または0になります)

注:戻り値はInt32であるため、このカウンターは約49。7日ごとにロールオーバーします。このような長い間隔を測定するために使用しないでください。

DateTime.Ticksは、 GetSystemTimeAsFileTime()WinAPI関数に基づいています。それは100ナノ秒(マイクロソコンドの10分の1)です。DateTime.Ticksの実際の精度は、システムによって異なります。XPでは、システムクロックの増分は約15.6ミリ秒で、Environment.TickCountの場合と同じです。Windows 7では、精度は1ミリ秒です(Environemnt.TickCountは15.6ミリ秒のままです)が、省電力スキームが使用されている場合(通常はラップトップで)、15.6ミリ秒まで低下する可能性があります。

StopwatchはQueryPerformanceCounter() WinAPI関数に基づいています(ただし、システムで高解像度のパフォーマンスカウンターがサポートされていない場合は、DateTime.Ticksが使用されます)

StopWatchを使用する前に、次の2つの問題に注意してください。

  • マルチプロセッサシステムでは信頼できない可能性があります(MS kb895980kb896256を参照) 。
  • CPU周波数が変化すると、信頼性が低下する可能性があります(この記事を読んでください)

簡単なテストでシステムの精度を評価できます。

static void Main(string[] args)
{
    int xcnt = 0;
    long xdelta, xstart;
    xstart = DateTime.UtcNow.Ticks;
    do {
        xdelta = DateTime.UtcNow.Ticks - xstart;
        xcnt++;
    } while (xdelta == 0);

    Console.WriteLine("DateTime:\t{0} ms, in {1} cycles", xdelta / (10000.0), xcnt);

    int ycnt = 0, ystart;
    long ydelta;
    ystart = Environment.TickCount;
    do {
        ydelta = Environment.TickCount - ystart;
        ycnt++;
    } while (ydelta == 0);

    Console.WriteLine("Environment:\t{0} ms, in {1} cycles ", ydelta, ycnt);


    Stopwatch sw = new Stopwatch();
    int zcnt = 0;
    long zstart, zdelta;

    sw.Start();
    zstart = sw.ElapsedTicks; // This minimizes the difference (opposed to just using 0)
    do {
        zdelta = sw.ElapsedTicks - zstart;
        zcnt++;
    } while (zdelta == 0);
    sw.Stop();

    Console.WriteLine("StopWatch:\t{0} ms, in {1} cycles", (zdelta * 1000.0) / Stopwatch.Frequency, zcnt);
    Console.ReadKey();
}
于 2012-01-14T21:42:17.563 に答える
72

ストップウォッチ クラスを使用します。msdn には適切な例があります: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

    Stopwatch stopWatch = Stopwatch.StartNew();
    Thread.Sleep(10000);
    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;
于 2008-10-28T13:41:34.097 に答える
28

なぜロールオーバーが心配なのですか?測定している期間が24。9日未満であり、相対的な期間を計算している限り、問題はありません。(開始点と終了点でより少ないまたはより多い比較を直接実行するのではなく)実行時間の自分の部分だけに関心がある限り、システムが実行されている時間は関係ありません。つまり、これ:

 int before_rollover = Int32.MaxValue - 5;
 int after_rollover = Int32.MinValue + 7;
 int duration = after_rollover - before_rollover;
 Console.WriteLine("before_rollover: " + before_rollover.ToString());
 Console.WriteLine("after_rollover: " + after_rollover.ToString());
 Console.WriteLine("duration: " + duration.ToString());

正しく印刷します:

 before_rollover: 2147483642
 after_rollover: -2147483641
 duration: 13

符号ビットについて心配する必要はありません。C#は、Cと同様に、CPUにこれを処理させます。

これは、組み込みシステムの時間カウントで私が以前に遭遇した一般的な状況です。たとえば、beforerollover<afterrolloverを直接比較することは決してありません。私は常に減算を実行してロールオーバーを考慮した期間を見つけ、それから他の計算を期間に基づいて行います。

于 2009-07-03T06:59:27.530 に答える
10

あなたはおそらくしたいですSystem.Diagnostics.StopWatch

于 2008-10-28T13:41:46.187 に答える
9

の機能を探しているが、新しいオブジェクトEnvironment.TickCountを作成するオーバーヘッドがない場合は、静的メソッドを (とともに) 使用して、長い期間を計算できます。を返すため、非常に長い間 (私がこれを書いているマシンでは 100,000 年以上) オーバーフローしません。また、最大分解能が 10 ~ 16 ミリ秒であるよりもはるかに正確です。StopwatchStopwatch.GetTimestamp()Stopwatch.FrequencyGetTimestamp()longEnvironment.TickCount

于 2011-06-10T15:37:18.400 に答える
8

使用する

System.Diagnostics.Stopwatch

と呼ばれる性質を持っています。

EllapsedMilliseconds
于 2008-10-28T13:42:01.443 に答える
0

ワンショットタイミングの場合は、さらに簡単に記述できます

Stopwatch stopWatch = Stopwatch.StartNew();
...dostuff...
Debug.WriteLine(String.Format("It took {0} milliseconds",
                              stopWatch.EllapsedMilliseconds)));

ElapsedTicks フィールドが長いことを考えると、TickCount での宇宙的に起こりそうにないラップアラウンドは、StopWatch にとってさらに懸念事項ではないと思います。私のマシンでは、StopWatch は 1 秒あたり 2.4e9 ティックの高解像度です。その速度でも、ダニのフィールドをオーバーフローするには 121 年以上かかります。もちろん、裏で何が起こっているかはわかりません。ただし、StopWatch のドキュメントではラップアラウンドの問題についても言及されていませんが、TickCount のドキュメントでは言及されています。

于 2009-03-17T00:25:11.097 に答える
0

私が Environment.TickCount を使用する理由は次のとおりです。

  1. Stopwatch クラスは Compact Framework にはありません。
  2. Stopwatch は、TickCount と同じ基礎となるタイミング メカニズムを使用するため、結果の精度は高くも低くもなりません。
  3. TickCount のラップアラウンドの問題は、宇宙的にヒットする可能性はほとんどありません(コンピューターを 27 日間実行したままにしてから、たまたまラップアラウンドの瞬間にまたがる時間を測定しようとする必要があります)。その結果、非常に大きな負の期間が発生します (そのため、目立ちます)。

そうは言っても、利用可能な場合は、ストップウォッチを使用することもお勧めします. または、約 1 分かけて、Environment.TickCount をラップするストップウォッチのようなクラスを作成することもできます。

ところで、ストップウォッチのドキュメントには、基礎となるタイマーメカニズムのラップアラウンドの問題について言及しているものは何もないので、ストップウォッチが同じ問題を抱えていることにまったく驚かない. しかし、繰り返しになりますが、私はそれについて心配することに時間を費やすつもりはありません。

于 2008-10-28T14:23:06.260 に答える
0

代わりにStopwatchクラスを使用する必要があります。

于 2008-10-28T13:42:12.847 に答える
0

私はそれをストップウォッチ クラスにラップすると言おうとしましたが、Grzenio はすでに正しいことを言っているので、私は彼にアップティックを与えます。このようなカプセル化は、どちらの方法が優れているかを決定する要素であり、これは時間の経過とともに変化する可能性があります。一部のシステムで時間を取得するのにどれほどの費用がかかるかにショックを受けたことを覚えています。そのため、最高の技術を実装できる 1 つの場所を持つことが非常に重要になる可能性があります。

于 2008-10-28T19:34:08.613 に答える