说实话,我的C#水平也不是很高,这几种C#字节数组的复制方法均是在网上搜来的,在进行测试后发现了一个有趣的问题,希望能和大家讨论一下。
首先是借鉴了文章《比较C#中几种常见的复制字节数组方法的效率 》,网址是:http://blog.csdn.net/jiangzhanchang/article/details/9998229,这篇文章中使用了4种方法,我这里对它进行了一个补充,增加了下面一片文章中的指针复制方法。
另一篇是微软官网《C#编程指南》中的《如何:使用指针复制字节数组(C# 编程指南)》,网址是:https://msdn.microsoft.com/zh-cn/library/28k1s2k6.aspx
下面是测试代码,主体结构是按照《比较C#中几种常见的复制字节数组方法的效率 》文章中的代码写的,后面只是增加了一部分指针复制的部分。
class Program { private const int TestTimes = 10000000; static void Main(string[] args) { var testArrayCopy = new TestArrayCopy(); TestCopy(testArrayCopy.TestBinaryReader, "Binary.ReadBytes"); TestCopy(testArrayCopy.TestConvertToList, "ConvertToList"); TestCopy(testArrayCopy.TestArrayDotCopy, "Array.Copy"); TestCopy(testArrayCopy.TestBlockCopy, "Buffer.BlockCopy"); TestCopy(testArrayCopy.TestPtrCopy, "PtrCopy"); Console.Read(); } private static void TestCopy(Action testMethod, string methodName) { var stopWatch = new Stopwatch(); stopWatch.Start(); for (int i = 0; i < TestTimes; i++) { testMethod(); } testMethod(); stopWatch.Stop(); Console.WriteLine("{0}: {1} seconds, {2}.", methodName, stopWatch.Elapsed.Seconds, stopWatch.Elapsed.Milliseconds); } }
class TestArrayCopy { private readonly byte[] _sourceBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; public void TestBinaryReader() { var binaryReader = new BinaryReader(new MemoryStream(_sourceBytes)); binaryReader.ReadBytes(_sourceBytes.Length); } public void TestConvertToList() { IList<byte> bytesSourceList = new List<byte>(_sourceBytes); var bytesNew = new byte[_sourceBytes.Length]; bytesSourceList.CopyTo(bytesNew, 0); } public void TestArrayDotCopy() { var bytesNew = new byte[_sourceBytes.Length]; Array.Copy(_sourceBytes, 0, bytesNew, 0, _sourceBytes.Length); } public void TestBlockCopy() { var bytesNew = new byte[_sourceBytes.Length]; Buffer.BlockCopy(_sourceBytes, 0, bytesNew, 0, _sourceBytes.Length); } public void TestPtrCopy() { var bytesNew = new byte[_sourceBytes.Length]; PtrCopy.Copy(_sourceBytes, 0, bytesNew, 0, _sourceBytes.Length); } }
接下来是指针复制的代码:class PtrCopy { public static unsafe void Copy(byte[] source, int sourceOffset, byte[] target, int targetOffset, int count) { // If either array is not instantiated, you cannot complete the copy. if ((source == null) || (target == null)) { throw new System.ArgumentException(); } // If either offset, or the number of bytes to copy, is negative, you // cannot complete the copy. if ((sourceOffset < 0) || (targetOffset < 0) || (count < 0)) { throw new System.ArgumentException(); } // If the number of bytes from the offset to the end of the array is // less than the number of bytes you want to copy, you cannot complete // the copy. if ((source.Length - sourceOffset < count) || (target.Length - targetOffset < count)) { throw new System.ArgumentException(); } // The following fixed statement pins the location of the source and // target objects in memory so that they will not be moved by garbage // collection. fixed (byte* pSource = source, pTarget = target) { // Set the starting points in source and target for the copying. byte* ps = pSource + sourceOffset; byte* pt = pTarget + targetOffset; // Copy the specified number of bytes from source to target. for (int i = 0; i < count; i++) { *pt = *ps; pt++; ps++; } } } }
下面是运行结果:Debug环境下:
Binary.ReadBytes: 1 seconds, 136.
ConvertToList: 1 seconds, 341.
Array.Copy: 0 seconds, 375.
Buffer.BlockCopy: 0 seconds, 291.
PtrCopy: 0 seconds, 475.
Release环境下:Binary.ReadBytes: 1 seconds, 108.
ConvertToList: 1 seconds, 262.
Array.Copy: 0 seconds, 330.
Buffer.BlockCopy: 0 seconds, 251.
PtrCopy: 0 seconds, 138.
从结果可以看出,同样的指针复制算法,在Debug环境下的速度不是最快的,只排在第三位,但是在Release环境下却是最快的,甚至比排在第二位的Buffer.BlockCopy方法快了将近一倍!这个是什么原因造成的?使用非安全代码会有什么样的问题?希望我这次的测试能够抛砖引玉,大家能够相互讨论一下。
关于C#中字节数组复制的五种方法
最新推荐文章于 2024-07-24 13:29:35 发布