赞
踩
本文测试了托管和非托管两种情况下,对数据访问的性能差异。数组长度为10M,执行叠加操作(即 arr[i] = arr[i] + arr[i+1]
),执行100次求平均时间。
测试环境:
注:StopWatch类是笔者自定义的计时工具,读者请使用一般计时方法替换。
public unsafe static void TestA() { int count = 10_000_000; double[] ds = new double[count]; var sws = StopWatch.Array(100); foreach (var sw in sws) { sw.Start("T1:Pointer"); // 非托管代码 unsafe { fixed (double* dp = ds) { for (int i = 0; i < count - 1; i++) dp[i] += dp[i + 1]; } } // 托管代码 sw.Start("T2:Managed"); for (int i = 0; i < count - 1; i++) ds[i] += ds[i + 1]; sw.StopAll(); } StopWatch.Analyze(sws); }
通过以下结果可以看出,在运行次数少的情况下,非托管代码的性能较托管代码强5%。而在测试次数增加到500次以后,结果更加稳定。笔者还做了其他一些数组操作的测试,也基本符合出这个结果。所以可以得到结果,在测试次数少的情况下,非托管代码性能略微强于托管代码,但提升有限;而当测试次数达到一定次数,性能差别基本可以忽略。所以,即便是在性能要求特别苛刻的情况下也不建议使用,因为非托管代码性能提升非常有限,却带来了一定的安全性的隐患(毕竟非托管指针更不安全)。所以,非托管的代码更多的目的是为了与一些C/C++编写的类库进行调用,而不是为了性能提升。
# 100 次的运行结果 ------------ Results.Median ------------ T1:Pointer: 19.0177 ms. T2:Managed: 20.0183 ms. ------------ Results.Sum ------------ T1:Pointer: 1981.78 ms. T2:Managed: 2040.88 ms. ------------ Results.Average ------------ T1:Pointer: 19.82 ms. T2:Managed: 20.41 ms. # 500次的运行结果 ------------ Results.Median ------------ T1:Pointer: 20.0183 ms. T2:Managed: 20.0185 ms. ------------ Results.Sum ------------ T1:Pointer: 10118.20 ms. T2:Managed: 10266.31 ms. ------------ Results.Average ------------ T1:Pointer: 20.24 ms. T2:Managed: 20.53 ms.
[1] Microsoft, How to use pointers to copy an array of bytes (C# Programming Guide), https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/unsafe-code-pointers/how-to-use-pointers-to-copy-an-array-of-bytes, 04/20/2018.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。