【发布时间】:2019-06-26 02:51:38
【问题描述】:
我使用 System.Diagnostics.StopWatch 类为 C# 创建了一个小型基准测试控制台应用程序,以观察 3 个方法需要多长时间:
我如何运行基准测试:
public void Run()
{
Stopwatch sw = new Stopwatch();
sw.Start();
InitDirectly();
sw.Stop();
Console.WriteLine($"InitDirectly: {sw.Elapsed.TotalMilliseconds}ms");
sw.Reset();
sw.Start();
InitWithAdd();
sw.Stop();
Console.WriteLine($"InitWithAdd: {sw.Elapsed.TotalMilliseconds}ms");
sw.Reset();
sw.Start();
InitWithForLoop();
sw.Stop();
Console.WriteLine($"InitWithForLoop: {sw.Elapsed.TotalMilliseconds}ms");
}
方法一:
private void InitListDirectly()
{
var list = new List<string>() {
"string",
"string",
"string",
//... up to a 100th entry
};
}
方法二:
private void InitListViaAdd()
{
var list = new List<string>();
list.Add("string");
list.Add("string");
list.Add("string");
//... up to a 100th entry
}
方法三:
private void InitListViaForLoop() {
var list = new List<string>();
for (int i = 0; i < 100; i++) {
list.Add("string");
}
}
现在在方法 1 之前启动秒表,然后停止。 方法 2 相同。
- 方法 1 耗时约 0.800 毫秒
- 方法 2 耗时约 1.000 毫秒
- 方法 3 耗时约 0.120 毫秒
现在我很惊讶,for 循环(方法 3)的速度如此之快。我希望方法 1 最快,因为其他两种方法必须调用“Add(string)”,而第三种方法必须创建一个 for 循环。
为什么方法 3 这么快?这是由于一些编译器魔法吗?它是否意识到 for 循环中的语句对于它的所有迭代都是相同的?
编辑:我在调试模式下运行。
【问题讨论】:
-
顺便说一下,Method1 和 Method2 在内部是相同的,列表初始化器的语法只是做大量
list.Add调用的糖。 -
你应该包括测试,因为我认为你测量不正确
-
我对你的结果持怀疑态度。你确定你的基准测试正确吗?
-
您是在发布模式还是调试模式下运行此代码?我怀疑如果您使用发布模式,这两种方法将花费相同的时间。
-
我用
bechmarkDotNet对此进行了基准测试,结果是:[922.054ns]、[921.826ns]、[946.982ns] 所以大致相等。您必须在发行版中编译,在没有调试器的情况下(从控制台)执行它并使用预热并取平均值。
标签: c# list initialization iteration benchmarking