簡単な例として、次の (不自然な) 例を考えてみましょう。
double Mean(List<double> items)
{
double mu = 0;
foreach (double val in items)
mu += val;
return mu / items.Length;
}
次のように時間を計ることができます。
void DoTimings(int n)
{
Stopwatch sw = new Stopwatch();
int time = 0;
double dummy = 0;
for (int i = 0; i < n; i++)
{
List<double> items = new List<double>();
// populate items with random numbers, excluded for brevity
sw.Start();
dummy += Mean(items);
sw.Stop();
time += sw.ElapsedMilliseconds;
}
Console.WriteLine(dummy);
Console.WriteLine(time / n);
}
これは、アイテムのリストが実際には非常に大きい場合に機能します。ただし、小さすぎる場合は、1 つのタイミングで複数回実行する必要があります。
void DoTimings(int n)
{
Stopwatch sw = new Stopwatch();
int time = 0;
double dummy = 0;
List<double> items = new List<double>(); // Reuse same list
// populate items with random numbers, excluded for brevity
sw.Start();
for (int i = 0; i < n; i++)
{
dummy += Mean(items);
time += sw.ElapsedMilliseconds;
}
sw.Stop();
Console.WriteLine(dummy);
Console.WriteLine(time / n);
}
2 番目の例では、リストのサイズが小さすぎる場合、これを十分な大きさで実行するだけで、所要時間を正確に把握できますn
。ただし、それぞれに利点と欠点があります。
ただし、これらのいずれかを実行する前に、事前に「ウォームアップ」計算を行います。
// Or something smaller, just enough to let the compiler JIT
double dummy = 0;
for (int i = 0; i < 10000; i++)
dummy += Mean(data);
Console.WriteLine(dummy);
// Now do the actual timing
両方の代替方法は、@Rig が彼の回答で行ったことを実行し、統計を行うための結果のリストを作成することです。最初のケースでは、個々の時間のリストを作成するだけです。2 番目のケースでは、複数の実行の平均タイミングのリストを作成します。これは、計算の時間がストップウォッチの最も細かい時間よりも短い可能性があるためです。
とはいえ、これらすべてには非常に大きな注意点が 1 つあります。何かを実行するのにかかる時間を正確に計算するのは非常に困難です。プロファイリングをしたいというのは素晴らしいことですが、SO について調査を行い、これを適切に行うために他の人が何をしたかを確認する必要があります。何かを悪いタイミングで実行するルーチンを作成するのは非常に簡単ですが、正しく実行するのは非常に困難です。