488

ボトルネックを見つけて、時間をできるだけ正確に測定する必要があります。

次のコード スニペットは、パフォーマンスを測定するための最良の方法ですか?

DateTime startTime = DateTime.Now;

// Some execution process

DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
4

16 に答える 16

663

いいえ、ちがいます。ストップウォッチを使用する(でSystem.Diagnostics)

Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

ストップウォッチは、高精度タイマーの存在を自動的にチェックします。

多くの場合、タイムゾーンやDSTなどで行わなければならない作業のために、DateTime.Nowかなり遅いことがあることに注意してください。DateTime.UtcNow

通常、DateTime.UtcNow の分解能は 15 ミリ秒です。優れた要約については、精度に関するJohn Chapman のブログ投稿を参照してください。DateTime.Now

DateTime.UtcNow興味深い雑学:ハードウェアが高頻度カウンターをサポートしていない場合、ストップウォッチはフォールバックします。Stopwatch がハードウェアを使用して高精度を実現しているかどうかは、静的フィールドStopwatch.IsHighResolutionで確認できます。

于 2008-08-26T17:13:32.240 に答える
94

素早く汚いものが必要な場合は、精度を高めるために代わりにストップウォッチを使用することをお勧めします。

Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();

Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);

または、もう少し洗練されたものが必要な場合は、おそらくANTSなどのサードパーティのプロファイラーの使用を検討する必要があります。

于 2008-08-26T17:15:20.723 に答える
60

この記事では、まず、3つの選択肢、、およびを比較する必要があると述べてStopwatchDateTime.NowますDateTime.UtcNow

また、場合によっては(パフォーマンスカウンターが存在しない場合)、StopwatchがDateTime.UtcNow+追加の処理を使用していることも示しています。そのため、その場合、DateTime.UtcNowが最良のオプションであることは明らかです(他の人がそれを使用し、いくつかの処理を行うため)

ただし、結局のところ、カウンターはほとんど常に存在します。高解像度パフォーマンスカウンターと、.NETストップウォッチに関連するその存在についての説明を参照してください。

これがパフォーマンスグラフです。UtcNowが他の方法と比較してパフォーマンスコストがいかに低いかに注目してください。

ここに画像の説明を入力してください

X軸はサンプルデータサイズであり、Y軸は例の相対時間です。

優れている点の1つStopwatchは、より高い分解能の時間測定を提供することです。もう1つは、よりOOな性質です。ただし、OOラッパーを作成するのはUtcNow難しいことではありません。

于 2011-08-08T18:04:04.890 に答える
19

ベンチマーク コードをユーティリティ クラス/メソッドにプッシュすると便利です。クラスは、またはエラーStopWatchである必要はありません。したがって、いくつかのアクションの時間を計測する最も単純なコードは次のとおりです。DisposedStopped

public partial class With
{
    public static long Benchmark(Action action)
    {
        var stopwatch = Stopwatch.StartNew();
        action();
        stopwatch.Stop();
        return stopwatch.ElapsedMilliseconds;
    }
}

サンプル呼び出しコード

public void Execute(Action action)
{
    var time = With.Benchmark(action);
    log.DebugFormat(“Did action in {0} ms.”, time);
}

これが拡張メソッドのバージョンです

public static class Extensions
{
    public static long Benchmark(this Action action)
    {
        return With.Benchmark(action);
    }
}

サンプル呼び出しコード

public void Execute(Action action)
{
    var time = action.Benchmark()
    log.DebugFormat(“Did action in {0} ms.”, time);
}
于 2008-09-02T15:25:41.570 に答える
17

ストップウォッチ機能の方が優れている(精度が高い)。ただし、人気のあるプロファイラーの 1 つをダウンロードすることもお勧めします ( DotTraceANTSは、私が最もよく使用したものです... DotTrace の無料試用版は完全に機能しており、他のプロファイラーのようにしつこくありません)。

于 2008-08-26T17:13:21.477 に答える
14

System.Diagnostics.Stopwatch クラスを使用します。

Stopwatch sw = new Stopwatch();
sw.Start();

// Do some code.

sw.Stop();

// sw.ElapsedMilliseconds = the time your "do some code" took.
于 2008-08-26T17:13:59.447 に答える
11

同上ストップウォッチ、それははるかに優れています。

パフォーマンス測定に関しては、「//実行プロセス」が非常に短いプロセスであるかどうかも確認する必要があります。

また、「// Some Execution Process」の最初の実行は、その後の実行よりも遅くなる可能性があることに注意してください。

通常、ループで 1000 回または 1000000 回実行してメソッドをテストすると、1 回実行するよりもはるかに正確なデータが得られます。

于 2008-08-30T14:24:33.147 に答える
9

これらはすべて時間を測定する優れた方法ですが、ボトルネックを見つけるには非常に間接的な方法にすぎません。

スレッド内のボトルネックを見つける最も直接的な方法は、スレッドを実行することです。スレッドが待機している間は、一時停止またはブレーク キーでスレッドを停止します。これを数回行います。ボトルネックに X% の時間がかかる場合、X% は、各スナップショットのアクションでボトルネックを検出する確率です。

これがどのように、そしてなぜ機能するのかについてのより完全な説明は次のとおりです

于 2009-01-27T20:16:57.637 に答える
7

これは正しい方法です:

using System;
using System.Diagnostics;

class Program
{
    public static void Main()
    {
        Stopwatch stopWatch = Stopwatch.StartNew();

            // some other code

        stopWatch.Stop();

        // this not correct to get full timer resolution
        Console.WriteLine("{0} ms", stopWatch.ElapsedMilliseconds);

        // Correct way to get accurate high precision timing
        Console.WriteLine("{0} ms", stopWatch.Elapsed.TotalMilliseconds);
    }
}

詳細については、正確なパフォーマンス カウンターを取得するために DataTime の代わりにストップウォッチを使用する を参照してください。

于 2011-03-06T16:21:47.057 に答える
7

@ショーン・チェンバーズ

参考までに、.NET Timer クラスは診断用ではありません。次のように、事前に設定された間隔でイベントを生成します ( MSDNから)。

System.Timers.Timer aTimer;
public static void Main()
{
    // Create a timer with a ten second interval.
    aTimer = new System.Timers.Timer(10000);

    // Hook up the Elapsed event for the timer.
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

    // Set the Interval to 2 seconds (2000 milliseconds).
    aTimer.Interval = 2000;
    aTimer.Enabled = true;

    Console.WriteLine("Press the Enter key to exit the program.");
    Console.ReadLine();
}

// Specify what you want to happen when the Elapsed event is 
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}

したがって、これは実際に何かにかかった時間を知るのに役立ちません。一定の時間が経過しただけです。

タイマーは、System.Windows.Forms のコントロールとしても公開されています。VS05/VS08 のデザイナー ツール ボックスで見つけることができます。

于 2008-08-26T17:22:15.790 に答える
6

Visual Studio Team Systemには、この問題に役立つ機能がいくつかあります。基本的に、単体テストを作成し、それらをさまざまなシナリオで組み合わせて、ストレスまたは負荷テストの一部としてソフトウェアに対して実行できます。これは、アプリケーションのパフォーマンスに最も影響を与えるコードの領域を特定するのに役立つ場合があります。

Microsoft の Patterns and Practices グループには、Visual Studio Team System Performance Testing Guidanceにいくつかのガイダンスがあります。

于 2008-10-25T12:14:06.043 に答える
5

私のプログラム内で使用する方法は、ここに示すように StopWatch クラスを使用することです。

Stopwatch sw = new Stopwatch();
sw.Start();


// Critical lines of code

long elapsedMs = sw.Elapsed.TotalMilliseconds;
于 2014-07-18T09:58:39.220 に答える
5

Vance Morrison のブログで、彼が書いた CodeTimer クラスStopWatchについての投稿を見つけました。

于 2008-10-08T21:02:03.380 に答える
4

私はこの種のパフォーマンス チェックをほとんど行ったことがないので (「これは遅いので、速くしてください」と考える傾向があります)、ほとんど常にこれを行ってきました。

グーグルは、パフォーマンスチェックのための多くのリソース/記事を明らかにします.

多くの人が pinvoke を使用してパフォーマンス情報を取得することに言及しています。私が研究している資料の多くは、perfmon の使用についてのみ言及しています。

編集:

ストップウォッチのトーク見た..いいね!私は何かを学びました:)

これは良い記事のようです

于 2008-08-26T17:14:44.170 に答える
4

これは十分に専門的ではありません。

Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

より信頼性の高いバージョンは次のとおりです。

PerformWork();

int repeat = 1000;

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < repeat; i++)
{
   PerformWork();
}

sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds / repeat);

実際のコードでは、GC.Collect 呼び出しを追加してマネージド ヒープを既知の状態に変更し、Sleep 呼び出しを追加して、コードのさまざまな間隔を ETW プロファイルで簡単に分離できるようにします。

于 2014-09-14T17:41:58.043 に答える