あなたの質問の基本的な問題は、単一の測定ですべての質問に答えることができるという仮定です。状況を効果的に把握するには、特にC#のようなガベージコレクションされた言語で複数回測定する必要があります。
別の答えは、基本的なパフォーマンスを測定する大丈夫な方法を提供します。
static void Profile(string description, int iterations, Action func) {
// warm up
func();
var watch = new Stopwatch();
// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
watch.Start();
for (int i = 0; i < iterations; i++) {
func();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.Elapsed.TotalMilliseconds);
}
ただし、この1回の測定ではガベージコレクションは考慮されません。適切なプロファイルは、多くの呼び出しにまたがるガーベッジコレクションの最悪の場合のパフォーマンスをさらに説明します(VMは、残されたガーベッジを収集せずに終了できるため、この数は無意味ですが、の2つの異なる実装を比較するのに役立ちfunc
ます。)
static void ProfileGarbageMany(string description, int iterations, Action func) {
// warm up
func();
var watch = new Stopwatch();
// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
watch.Start();
for (int i = 0; i < iterations; i++) {
func();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.Elapsed.TotalMilliseconds);
}
また、1回だけ呼び出されるメソッドのガベージコレクションの最悪の場合のパフォーマンスを測定することもできます。
static void ProfileGarbage(string description, int iterations, Action func) {
// warm up
func();
var watch = new Stopwatch();
// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
watch.Start();
for (int i = 0; i < iterations; i++) {
func();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
watch.Stop();
Console.Write(description);
Console.WriteLine(" Time Elapsed {0} ms", watch.Elapsed.TotalMilliseconds);
}
ただし、プロファイルに特定の可能な追加の測定を推奨するよりも重要なのは、1種類の統計だけでなく、複数の異なる統計を測定するという考えです。