你的问题基本上存在一个假设,即单次测量可以回答你所有的问题。你需要多次测量才能有效地了解情况,特别是在像C#这样的垃圾收集语言中。
另一个答案提供了一种衡量基本性能的可行方法。
static void Profile(string description, int iterations, Action func) {
func();
var watch = new Stopwatch();
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);
}
然而,这个单一的度量并没有考虑到垃圾回收。一个合适的性能分析还要考虑到垃圾回收在多次调用中的最坏情况性能(这个数字有点无用,因为虚拟机可以在不收集剩余垃圾的情况下终止,但对于比较两个不同的
func
实现仍然很有用)。
static void ProfileGarbageMany(string description, int iterations, Action func) {
func();
var watch = new Stopwatch();
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) {
func();
var watch = new Stopwatch();
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);
}
但比推荐任何特定的可能的额外测量更重要的是,应该测量多种不同的统计数据,而不仅仅是一种统计数据。