您的问题的基本问题是一种假设,即一次测量即可回答所有问题。您需要进行多次测量才能获得对情况的有效了解,尤其是在像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可以终止而无需收集剩余的垃圾,但对于比较的两种不同实现仍然有用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);
}
但是,比建议对任何可能的其他度量进行概要描述更重要的是,一个想法应该度量多个不同的统计数据,而不仅仅是一种统计数据。