我有以下插入排序算法实现:
private static void InsertionSort(List<int> array)
{
for (int i = 1; i < array.Count; ++i)
{
for (int j = i; j > 0 && array[j - 1] > array[j]; --j)
{
//swap(array, j, j-1);
int temp = array[j];
array[j] = array[j-1];
array[j-1] = temp;
}
}
}
private static void swap(List<int> array, int i, int j)
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
当我使用 swap(array, j, j-1);
运行我的算法时,它比我使用内联函数主体花费更多的时间(50000 个元素 +2 秒)。
为什么?
最佳答案
手动内联方法并没有错,只是没有必要。内联小方法是 standard optimizations 之一由抖动执行。这种情况并不总是发生,但在 .NET 4.6.1 上,x86 和 x64 抖动都做在此示例代码中内联 swap()。此外,他们还展开内部循环以在每次传递时产生两次 交换,这种手动优化程序员通常会跳过。
正确地对 .NET 应用程序进行基准测试并不总是那么简单。 非常对于运行程序的发布版本非常重要。并不使用调试器。尽管后者很容易修复,请使用工具 > 选项 > 调试 > 常规 > 取消选中“抑制 JIT 优化”选项。没有充分的理由将其重新打开。
您现在还可以看到生成的机器代码,在 InsertionSort() 上设置断点,当它命中时使用 Debug > Windows > Disassembly。往往让人眼睛流血,但很容易看出你得到了两个内联的 swap()。我会把程序集转储留给你,看一看。你应该清楚地看到测量的差异。这是我得到的:
在 x64 上使用 swap() 在具有 50,000 个随机整数的列表上运行它 5 次:
00:00:05.4447216
00:00:05.2928558
00:00:05.6960587
00:00:05.2835343
00:00:05.2809591
相同的测试,但现在手动内联 swap():
00:00:05.3015856
00:00:05.2877402
00:00:05.6369775
00:00:05.2603384
00:00:05.2616389
需要尽可能长的时间。
如果不显示使用 List.Sort() 得到的结果,我会失职:
00:00:00.0075878
00:00:00.0073398
00:00:00.0076528
00:00:00.0078046
00:00:00.0066319
关于c# - 为什么函数调用要花这么多时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37632161/