本文来对比多个不同的方法进行数组拷贝,和测试其性能
测试性能必须采用基准(标准)性能测试方法,否则测试结果不可信。在 dotnet 里面,可以采用 BenchmarkDotNet 进行性能测试。详细请看 C# 标准性能测试
拷贝某个数组的从某个起始点加上某个长度的数据到另一个数组里面,可选方法有很多,本文仅列举出使用 for
循环拷贝,和使用 Array.Copy 方法和用 Span 方法进行拷贝进行对比
假定有需要被拷贝的数组是 TestData
其定义如下
使用 for
循环拷贝的方法如下
以上代码返回 data 作为 object 仅仅只是为了做性能测试,避免被 dotnet 优化掉
另一个拷贝数组是采用 Array.Copy
拷贝,逻辑如下
采用新的 dotnet 提供的 Span 进行拷贝,代码如下
接着加上一些性能调试辅助逻辑
在我的设备上的测试效果如下
可以看到,在对比使用 for
循环拷贝和使用 Array.Copy
拷贝中,使用 Array.Copy
拷贝的性能更好,在拷贝的数组长度越长的时候,使用 Array.Copy 拷贝性能优势就更好
接下来再加上 Span 的性能比较,如下面代码
性能对比测试如下
可以看到 Span 的性能比 Array.Copy
拷贝性能更强
在 Span 里面,转换为数组的逻辑如下
这里使用到的 Buffer 的有黑科技的 Memmove 方法,此方法的实现如下
以上性能测试使用的是 int 数组,刚好能进入 Memmove 的分支,而不是 BulkMoveWithWriteBarrier 这个分支。在里层的 Memmove 方法里面用到了很多黑科技,本文只是用来对比多个方法拷贝数组的性能,黑科技部分就需要大家自己去阅读 dotnet 的源代码啦
另外,如果需要做完全的数组的拷贝,数组里面存放的是值类型对象,如 int 类型,那么拷贝整个数组还有另一个可选项是通过 Clone
方法进行拷贝,代码如下
使用 Clone
的方法的行为是返回数组的浅表拷贝,也就是说数组里面的元素没有做深拷贝,只是拷贝数组本身而已。对于值类型来说,就没有啥问题了
稍微更改一下性能测试,更改的代码如下
通过下图可以了解到采用 Clone 方法和采用 Array.Copy 方法的性能差不多,但 Clone 稍微快一点
以上是给 WPF 框架做性能优化时测试的,详细请看
特别感谢ThomasGoulet73大佬教我使用 AsSpan 的方法拷贝数组
原文链接: http://blog.lindexi.com/post/dotnet-6-%E6%95%B0%E7%BB%84%E6%8B%B7%E8%B4%9D%E6%80%A7%E8%83%BD%E5%AF%B9%E6%AF%94
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。