在C#中,我如何获取字节数组的子数组,例如:
byte[] arrByte1 = {11,22,33,44,55,66}
我需要参考两个字节的子数组,例如33和44的值。
有多种选项可供选择,比如使用Array.Copy、ArraySegment、LINQ(Skip和Take)等等。从性能的角度来看,哪种方法最好呢?
在C#中,我如何获取字节数组的子数组,例如:
byte[] arrByte1 = {11,22,33,44,55,66}
我需要参考两个字节的子数组,例如33和44的值。
有多种选项可供选择,比如使用Array.Copy、ArraySegment、LINQ(Skip和Take)等等。从性能的角度来看,哪种方法最好呢?
简单性能测试:
public void Test()
{
const int MAX = 1000000;
byte[] arrByte1 = { 11, 22, 33, 44, 55, 66 };
byte[] arrByte2 = new byte[2];
Stopwatch sw = new Stopwatch();
// Array.Copy
sw.Start();
for (int i = 0; i < MAX; i++)
{
Array.Copy(arrByte1, 2, arrByte2, 0, 2);
}
sw.Stop();
Console.WriteLine("Array.Copy: {0}ms", sw.ElapsedMilliseconds);
// Linq
sw.Restart();
for (int i = 0; i < MAX; i++)
{
arrByte2 = arrByte1.Skip(2).Take(2).ToArray();
}
sw.Stop();
Console.WriteLine("Linq: {0}ms", sw.ElapsedMilliseconds);
}
结果:
Array.Copy: 28ms
Linq: 189ms
大数据性能测试:
public void Test()
{
const int MAX = 1000000;
int[] arrByte1 = Enumerable.Range(0, 1000).ToArray();
int[] arrByte2 = new int[500];
Stopwatch sw = new Stopwatch();
// Array.Copy
sw.Start();
for (int i = 0; i < MAX; i++)
{
Array.Copy(arrByte1, 500, arrByte2, 0, 500);
}
sw.Stop();
Console.WriteLine("Array.Copy: {0}ms", sw.ElapsedMilliseconds);
// Linq
sw.Restart();
for (int i = 0; i < MAX; i++)
{
arrByte2 = arrByte1.Skip(500).Take(500).ToArray();
}
sw.Stop();
Console.WriteLine("Linq: {0}ms", sw.ElapsedMilliseconds);
}
结果:
Array.Copy: 186ms
Linq: 12666ms
正如你所看到的,对于大数据,linq 会出现问题。
sw.Restart()
,否则sw.ElapsedMilliseconds
也会包括Array.Copy()
的毫秒数。 - Luis E. FraguadaBuffer.Copy()
测试:https://gist.github.com/fraguada/301fe31b939e6889514969cb1bbec37c - Luis E. FraguadaBuffer.BlockCopy 对于字节数组而言比 Array.Copy 更快。
Buffer.BlockCopy()
确实更快。我已经添加了一个测试Buffer.BlockCopy()
和ArraySegment<int>().ToArray()
的gist:https://gist.github.com/fraguada/301fe31b939e6889514969cb1bbec37c - Luis E. Fraguada使用 Array.Copy。
示例:
int[] target = new int[2];
Array.Copy(arrByte1, 2, target, 0, 2);
格式:
Array.Copy(source, source index, target, target index, length);