2011-01-11 10 views
5

本当に、私は、Windowsオペレーティングシステムで特定のC#関数の時間サイクルを正確に測定する優れた関数を探しています。私は、これらの機能を試してみましたが、どちらも正確な測定を得ることはありません:C#関数の時間サイクルを測定する最も良い方法は何ですか?

DateTime StartTime = DateTime.Now;  
TimeSpan ts = DateTime.Now.Subtract(StartTime); 
Stopwatch stopWatch = new Stopwatch(); 
stopWatch.Start(); 
//code to be measured 
stopWatch.Stop(); 
TimeSpan ts = stopWatch.Elapsed; 

本当に、私はそれらを呼び出すたびに、彼らは私に同じ機能のための別の時間を与える

をしてください、誰もがより良い方法を知っていれば時間を正確に計る、助けてくれてありがとう、たくさんあります。

答えて

7

機能を実行するのにかかる時間を測定するには、ストップウォッチをお勧めします。さまざまなソフトウェアやハードウェアの要因により、実行から実行までは同じではありません。そのため、通常は多数の実行でパフォーマンス分析が行われ、時間が平均化されます。

+0

お返事ありがとうございます。実行回数の多い平均時間を取る代わりに、他のプロセスの影響を受けることなく、自分のコードプロセスのクロックサイクルだけを測定する方法について聞きましたか? – Duaa

4

"彼らは私に同じ機能のために異なる時間を与えます" - これは期待されています。あなたはシステム上で実行されている唯一のプロセスではないので、状況は変動します。

大きなループで時間を計るコードを実行して、変動を平均化します(合計時間をループ数で割る)。

Stopwatchは正確なタイマーであり、ほとんどの状況では適切なタイミングよりも優れています。

const int numLoops = 1000000; // ...or whatever number is appropriate 

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

for (int i = 0; i < numLoops; i++) 
{ 
    // code to be timed... 
} 

stopWatch.Stop(); 
TimeSpan elapsedTotal = stopWatch.Elapsed; 
double timeMs = elapsedTotal.TotalMilliseconds/numLoops; 
+0

+1と私は常に、現在のプロセス/スレッド優先度を最高に設定して測定します。 –

+0

あなたの返事をありがとうが、私はコードが長いので、私は1000000回のaloopで私のコードを繰り返すことはできないと思う、それはあまりにも時間が待っているだろう...私の他のプロセスの影響を受けることなく、 – Duaa

+0

ループのサイズを1000とすると、10000 –

1

ゴールドスタンダードはStopWatchです。それは高解像度タイマーであり、非常にうまく動作します。

私はあなたがあなたのintを与えるdoubleではなく.Elapsed.MilliSecondsを取得するようお.Elapsed.TotalMilliSecondsを使用して経過時間を確認してくださいお勧めしたいです。これはあなたの結果を投げ捨てているかもしれません。

また、タイミングテスト中にガベージコレクションが行われ、結果として時間が大幅に変更されることがあります。タイミングテストの前後でGC収集数を確認し、ガベージコレクションが発生した場合はその結果を破棄すると便利です。

そうしないと、テスト中にほかのスレッドやプロセスがCPUやその他のシステムリソースを引き継ぐことがあるため、結果が単純に異なる場合があります。テストを複数回実行し、統計的に平均を計算することによって結果を分析することを除いてここで行うことはあまりありません。&標準偏差のタイミングなど

これが役立ちます。

+0

あなたの返信ありがとうございました...多数のランに沿って平均時間を取るのではなく、私の他のプロセスの影響を受けることなく、 – Duaa

+0

@Duaa - AFAIKあなたがコードを最初に実行できるようにするためには、オペレーティングシステムのプロセスが必要なので、これが当てはまることを保証する方法はありません。あなたがそれらを止めることができれば、あなたのコードも停止し、あなたはどんなタイミングもすることができません。テストでは、他のプロセスやスレッドを許可する必要があります。このため、統計を使用する必要があります。 – Enigmativity

+0

あなたの返信をありがとう – Duaa

1

クロックサイクルでコードを測定することは可能ですが、それはまだ秒単位での測定と同じくらいばらつきがあります。秒はそれほど良くないとは限りません。クロックサイクルよりも測定単位)。他のプロセスの影響を受けない測定値を取得する唯一の方法は、実行中のものがないことを確認することです.Windows上で実行することはできません.OS自体は、シングルプロセスOSではないため、 。

あなたが望む測定値に最も近いのは、コードas described hereを構築して実行することです。次に、コードの先頭にブレークポイントを設定してステップ実行することで、時間を計りたいメソッドのJITコードのx86アセンブリを表示できます。各x86命令は、インテル®アーキテクチャー・マニュアルのサイクル・タイミングと相互参照し、正確なサイクル・カウントを得るためにそれらを追加することができます。

これはもちろん、非常に苦痛で基本的に役に立たない。また、JITがあなたのILからx86を作成するために若干異なるアプローチを取るコード変更によって無効になるかもしれません。

+0

返信ありがとう – Duaa

0

他をエコーするには:Stopwatchクラスがこれを行うための最良の方法です。

クロックサイクルの測定に関する質問にお答えします。最新のプロセッサでマルチタスキングOSで実行しているという事実は、クロックサイクルの測定をほとんど役に立たなくします。コンテキストスイッチはプロセッサキャッシュからコードとデータを削除する可能性が高く、その間にOSは作業セットを交換することになります。

プロセッサは、キャッシュ待機またはメモリアクセスに基づいて命令の順序を変更し、待機中に実行できる命令を実行することができます。または、キャッシュ内にある場合はそうでないかもしれません。

つまり、要するに、複数のランを実行し、それらを平均化することは、本当に唯一の方法です。

時間内のジッタを少なくするには、スレッド/プロセスの優先度を上げることができますが、これは他の問題が発生する可能性があります(リアルタイム優先度にぶつかり、バグが発生し、無限ループに陥った場合、唯一の選択肢はリセットボタンです)、特にユーザーのコンピュータや運用環境ではお勧めできません。それが重要な場所では実行できないため、マシンで実行したベンチマークを優先順位の変更を加えて無効にします。

+0

返信ありがとうございました – Duaa

1

コード実行を測定するにはプロファイラが必要です(検索を開始するにはWhat Are Some Good .NET Profilers?を参照)。

あなたのコメントを見て、あなたが最適化しようとしているものは不明です。一般的には、コードが1000回実行され、純粋にCPUにバインドされている場合、CPUクロックサイクルを測定する必要があります。他の場合は、関数ごとの実行時間で十分です。しかし、あなたのコードはストップウォッチで平均時間を計算するために何度も実行するには遅すぎると言っています。

また、CPUがアプリケーションのボトルネックになっているのか、それとも遅くなるのかが分かっている必要があります。 TaskManagerのCPU%を見ると、100%のCPU使用率を下回る情報が得られ、プログラムの速度を遅くする何か(ネットワークやディスクアクティビティなど)があることがほとんど保証されます。

基本的に、パフォーマンス目標を達成するために測定しようとしているコードの種類についてより詳細な情報を提供することで、より簡単に役立ちます。

+0

返事ありがとうございました...私は時間を測定しようとしていますが、C#でプログラムした修正された文字列マッチングアルゴリズムです。他の文字列一致アルゴリズム、特に時間measurmenetの場合、私の変更された文字列照合アルゴリズムが他のものより高速であることを保証する...ありがとう – Duaa

0

を使用して開始と終了をキャプチャし、次にTimeSpan.FromTicks()をキャプチャする方法はありますか?

関連する問題