编程文汇

pInvoke调用c函数与调用c#函数效率对比

#1

对比一个简单的add操作,代码如下:

        static void perf()
        {
            const int N = 100000000;
            const int M = 123;
            {
                long start = Ezg.ezg_now();
                long ret = 0;
                for (int i = 0; i < N; i++)
                {
                    ret = Ezg.add(ret, i%M);//c函数
                    ret %= M;
                }
                Ezg.log((Ezg.ezg_now() - start) + "");
                Ezg.log("" + ret);
            }
            {
                long add(long a,long b)
                {
                    return a + b;
                }
                long start = Ezg.ezg_now();  
                long ret = 0;
                for (int i = 0; i < N; i++)
                {
                    ret = add(ret, i % M); //本地函数
                    ret %= M;
                }
                Ezg.log((Ezg.ezg_now() - start) + "");
                Ezg.log("" + ret);
            }
            {
                long add(long a, long b)
                {
                    return a + b;
                }
                long start = Ezg.ezg_now();
                long ret = 0;
                for (int i = 0; i < N; i++)
                {
                    ret += (i % M); //直接用+
                    ret %= M;
                }
                Ezg.log((Ezg.ezg_now() - start) + "");
                Ezg.log("" + ret);
            }
        }

release运行结果如下:

2512
120

704
120

696
120

调用c函数的速度比我预想的速度要快(2.5秒),我以为会有明显的跨界调用开销,与c#调用自己的add相比(0.7秒),这个开销还是挺低的。基本上和unsafe下直接访问非托管内存差不多。这个性能下降很可能和编译器不能做优化有关。

所以c#调用用c,速度还是很快的,与调用自身函数速度基本相当(要比java的jni速度快的多)。所以,只有参数是数据或者大型数据结构时,需要拷贝、转换大量数据,才会慢。所以,如果参数都是除开string之外的基本类型,native调用可以敞开使用。

JNI的调用开销,stackoverflow上的回答