1

当我从 C# 调用 ummanaged dll 时,我已经对 C# 和 C 中 for 循环的性能进行了一些测试...

结果令我惊讶的是,随着循环越过更大的范围,与 C 相比,C# 的性能下降。对于较小的范围,C# 表现出优于 C 的良好性能....但是,作为 for 循环的上限增加,与 C 相比,C# 性能下降。

这是我的测试代码....

    [DllImport("Testing.dll", CallingConvention =  CallingConvention.Cdecl)]
    public static extern int SumLoop(int lowLimit, int highLimit);

    public static void Main(string[] args)
    {
        const int LowerRange = 1;
        const int HigherRange = 1000000;

        // Test with C# For Loop
        var watch1 = new Stopwatch();
        watch1.Start();
        int sum = 0;
        for (int i = LowerRange; i <= HigherRange; i++)
        {
            sum += i;
        }
        watch1.Stop();

        long elapseTime1 = watch1.ElapsedMilliseconds;

        // Test with C-for loop
        var watch2 = new Stopwatch();
        watch2.Start();
        int sumFromC = SumLoop(LowerRange , HigherRange);
        long elapseTime2 = watch2.ElapsedMilliseconds;
   }

测试.dll:

__declspec(dllexport) int SumLoop(int lowLimit, int highLimit)
{
    int idx;
    int totalSum = 0;
    for(idx = lowLimit;idx<= highLimit; idx= idx +1)
    {
        totalSum += idx;
    }
    return totalSum;
}

测试结果:

测试1:

更高范围:1000000

C#循环:4毫秒

C循环:9毫秒

测试 2:

更高范围:10000000

C# 循环:53 毫秒

C循环:36毫秒

测试 3:

更高范围:100000000

C# 循环:418 毫秒

C循环:343毫秒

在这里,我开始进行上面的测试,目的是 C for 循环的性能将优于 C# 循环,但这与我的理解完全相反,并同意这个问题并同意......但是当我增加 for 循环的上限时,与 C# 相比,C 的性能表现良好......

现在,我在想测试的方法是错误的还是预期的性能结果?

4

1 回答 1

3

这里发生的是您忽略了使用 P/Invoke 调用 C 函数的固定开销。

C 函数比 C# 版本更快,但由于调用它的开销相对较大,C 函数对于小数组会显得较慢,因为调用开销占总时间的比例相对较大。

但是,随着集合大小的增加,开销在总时间中所占的比例会越来越小,直到 C 版本的额外速度出现并且您开始看到它运行得更快。

如果您查看 C# 函数的时间,您会发现它确实与 N 或多或少呈线性增加,这是您所期望的。将 N 增加 100 倍后,将 T = 4 与 T = 418 进行比较。这正是您所期望的。但是由于上述原因,C 次似乎并没有线性增加。

顺便说一句,如果您至少需要两次计时,则可以使用联立方程来求解:

T = K + XN

其中 K 是固定开销,X 是每个元素的开销。

我根据您的时间计算得出,调用非托管代码的固定开销约为 5.6 毫秒,每个元素的开销为 3.373737 x 10^-6 毫秒。

这个开销似乎有点大,但我猜测量的数据有一些不准确之处。

于 2013-02-19T09:18:56.450 回答