질문의 기본 문제는 단일 측정으로 모든 질문에 답할 수 있다는 가정입니다. 상황, 특히 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);
}
그러나이 단일 측정은 가비지 수집을 고려하지 않습니다. 적절한 프로필은 추가로 많은 호출에 걸쳐 분산 된 가비지 수집의 최악의 경우 성능을 설명합니다 (이 숫자는 VM이 남은 가비지 수집없이 종료 될 수 있지만 .NET의 두 가지 구현을 비교하는 데 여전히 유용하므로 쓸모가 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);
}
또한 한 번만 호출되는 메서드에 대해 가비지 수집의 최악의 성능을 측정 할 수도 있습니다.
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);
}
그러나 프로파일 링 할 특정 가능한 추가 측정을 권장하는 것보다 더 중요한 것은 한 종류의 통계가 아닌 여러 다른 통계를 측정해야한다는 생각입니다.