为什么函数调用需要这么多时间?

时间:2016-06-04 15:49:03

标签: c# algorithm performance

我有以下插入排序算法实现:

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秒),而不是我的函数体内联。

为什么?

1 个答案:

答案 0 :(得分:15)

手动内联方法没有错,只是没有必要。内联小方法是抖动执行的standard optimizations之一。这并不总是发生,但在.NET 4.6.1中,x86和x64抖动在此示例代码中执行内联交换()。而且,他们还展开内部循环以产生每次传递两个交换,这种手动优化程序员通常会跳过。

正确地对.NET应用程序进行基准测试并不总是那么直截了当。 非常运行程序的Release版本非常重要。并且使用调试器。虽然后者易于修复,但请使用工具&gt;选项&gt;调试&gt;一般&gt;取消勾选“抑制JIT优化”选项。没有充分理由重新开启。

您现在还可以看到生成的机器代码,在InsertionSort()上设置断点以及何时命中使用Debug&gt; Windows&gt;拆卸。倾向于让人们的眼睛流血,但很容易看到你得到两个内联交换()。我会把你的汇编转储给你,只是看看吧。你应该清楚地看到测量的差异。这是我得到的:

在x64上使用带有50,000个随机整数的List上的swap()运行它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