メソッドの実行時間を計算する


533

重複の可能性:
関数の実行時間を測定するにはどうすればよいですか?

ある場所から別の場所にデータをコピーするI / O時間のかかる方法があります。実行時間を計算するための最良かつ最も現実的な方法は何ですか?ThreadTimerStopwatch?他の解決策はありますか?私は最も正確で、できるだけ短いものを求めています。

回答:


1131

Stopwatch はこの目的のために設計されており、.NETでの時間実行を測定する最良の方法の1つです。

var watch = System.Diagnostics.Stopwatch.StartNew();
// the code that you want to measure comes here
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;

.NETでの時間実行の測定に DateTime使用しないでください


更新:

コメントセクションの@ series0neで指摘されているように、一部のコードの実行を正確に測定するには、オペレーティングシステムに組み込まれているパフォーマンスカウンターを使用する必要があります。以下の答えは、素敵な概要が含まれています。


2
正確に、そしてこの場合はどうですか:私はThreadPool.QueueUserWorkItem(delegate { CopyFiles(folder, dest); }); 内部にforeachループがありますが、ストップウォッチはすべてが完了する前に停止します。
Mahdi Tahsildari

13
@DarinDimitrov-ストップウォッチは完全に正確ではありませんか?.NETバックグラウンドノイズ(JITingなど)により、実行時間が変化することに注意してください。したがって、現実的には、正確な測定のために、OPはパフォーマンスプロファイラーを使用する必要があります。
マシューレイトン

3
@ series0ne、非常に良い点。私はあなたの貴重なコメントを含めるために私の答えを更新します。
Darin Dimitrov

7
@DarinDimitrov、私は最近、非常に熟練した上級開発者にインタビューをしました。彼は、DateTimesを使用する方が、StopWatchを使用するよりも実際には正確であると私に指摘しました。この理由は、.NETのストップウォッチではCPUアフィニティが考慮されないため、スレッドがあるコアから別のコアに移動した場合、他のコアの実行時間は考慮されないためです。スレッドが実行を開始したもののみ。これについてどう思いますか?
マシューレイトン

2
@ series0ne、上級開発者がストップウォッチとDateTimeについてあなたに言ったことは絶対に本当です。ただし、DateTimeの場合、十分な精度がありません。問題は、それらすべての機能を許可するような.NETのクラスが存在しないことです。
Darin Dimitrov

75

個人的な経験から、System.Diagnostics.Stopwatchクラスはメソッドの実行時間を測定するために使用することができ、しかし、用心:それは完全に正確ではありません!

次の例を考えてみます。

Stopwatch sw;

for(int index = 0; index < 10; index++)
{
    sw = Stopwatch.StartNew();
    DoSomething();
    Console.WriteLine(sw.ElapsedMilliseconds);
}

sw.Stop();

結果の例

132ms
4ms
3ms
3ms
2ms
3ms
34ms
2ms
1ms
1ms

今、あなたは疑問に思っています。「まあ、なぜ最初に132msかかり、残りの時間が大幅に減ったのですか?」

答えは、StopwatchJITingなどの.NETの「バックグラウンドノイズ」アクティビティを補正しないことです。したがって、メソッドを初めて実行するときは、.NET JITが最初です。これを実行するのにかかる時間は、実行時間に追加されます。同様に、他の要因も実行時間を変化させます。

絶対的な精度を本当に求めているのは、パフォーマンスプロファイリングです。

以下を見てください。

RedGate ANTS Performance Profilerは商用製品ですが、非常に正確な結果が得られます。- .NETプロファイリングを使用してアプリケーションのパフォーマンスを向上

次に、プロファイリングに関するStackOverflowの記事を示します。-優れた.NETプロファイラーとは

また、ストップウォッチを使用したパフォーマンスプロファイリングに関する記事も書いています-.NETでのパフォーマンスプロファイリング


2
@mahditahsildari問題ありません。お役に立てて嬉しいです!:-)
マシューレイトン

41
これが不正確な例である理由がわかりません。ストップウォッチは最初の呼び出しの総コストを正確に測定しています。これは確かに、このコードを実行する予定の顧客に関連するものです。これらの132ミリ秒がメソッドの実行とジッターのどちらに課されるかは関係なく、経過時間の合計が関係します。
Eric Lippert

2
@ series0neループのパフォーマンスを気にする場合は、ループのパフォーマンスを測定します。何かをn回実行すると、それを1回実行するよりもn倍遅くなると単純に想定しないでください。
スビック

3
最初に、StopWatchがループでリセットされることはないため、コードサンプルは、増加する数で出力を生成する必要があります。そして、「すべき」とはそうだということです(私はチェックしました)。したがって、出力はコードと一致しません。次に、ループ内でStop / Write / Reset / Startを実行するようにコードを修正したところ、最初の測定は残りの測定と同じでした。私の推測では、DoSomethingは最初に実行されたときに長時間何かを実行しています。JITが原因である場合とそうでない場合がありますが、ストップウォッチが測定に影響しているわけではありません。したがって、-1。
ILIA BROUDNO

2
ILIA BROUDNOは完全に正しいです、私は同じ結果を得ました。@ series0ne、ループ内にConsole.WriteLineがあり、これまでにmsを書き込んでいます。ループが終了した後にのみウォッチを停止するため、反復ごとに時間とともに増加します。実行中に時間が累積すると、3、6、10、12、15などのようになります。
Rui Miguel Pinheiro 2018年

29

StopWatch クラスはあなたの最善の解決策を探します。

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

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

また、という静的フィールドがありますStopwatch.IsHighResolution。もちろん、これはハードウェアとオペレーティングシステムの問題です。

タイマーが高解像度パフォーマンスカウンターに基づいているかどうかを示します。


18

パフォーマンスの理解に興味がある場合は、プロファイラーを使用するのが最善の方法です。

それ以外の場合、System.Diagnostics.StopWatchは高解像度タイマーを提供します。


正解です。完全に正確ではないので、ここの多くの人がストップウォッチの使用を提案していることに少し落胆しています。ただし、パフォーマンスプロファイラーの使用を提案したとおり、これが正しい方法です。+1
マシュー・レイトン

7

ストップウォッチは高解像度カウンターを使用します

ストップウォッチは、基になるタイマーメカニズムのタイマーティックをカウントすることによって経過時間を測定します。インストールされているハードウェアとオペレーティングシステムが高解像度のパフォーマンスカウンターをサポートしている場合、Stopwatchクラスはそのカウンターを使用して経過時間を測定します。それ以外の場合、Stopwatchクラスはシステムタイマーを使用して経過時間を測定します。FrequencyおよびIsHighResolutionフィールドを使用して、ストップウォッチタイミング実装の精度と分解能を決定します。

IOを測定している場合、数値は外部イベントの影響を受ける可能性があり、私は非常に心配しています。正確さ(上記で示したとおり)。代わりに、さまざまな測定を行い、それらの数値の平均と分布を検討します。


0
 using System.Diagnostics;
 class Program
 {
    static void Test1()
    {
        for (int i = 1; i <= 100; i++)
        {
            Console.WriteLine("Test1 " + i);
        }
    }
  static void Main(string[] args)
    {

        Stopwatch sw = new Stopwatch();
        sw.Start();
        Test1();
        sw.Stop();
        Console.WriteLine("Time Taken-->{0}",sw.ElapsedMilliseconds);
   }
 }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.