c#抓取网页数据( 这篇就是分享:各种数组赋值转换的方法和结果对比)
优采云 发布时间: 2021-12-16 01:19c#抓取网页数据(
这篇就是分享:各种数组赋值转换的方法和结果对比)
浅谈C#中各种数组的直接数据拷贝/转换
更新时间:2016-08-23 09:48:40 投稿:景贤
下面小编就为大家带来一篇关于C#中各种数组的直接数据复制/转换的文章。我觉得还不错,现在分享给大家,给大家参考。跟着小编一起来看看吧
之前我用C#的SharpGL库做Opengl程序,里面有各种奇怪的绑定函数,比如原型是:
void glInterleavedArrays(uint format, int stride, void * pointer);
该函数绑定到:
private static extern void glInterleavedArrays(uint format, int stride, int[] pointer);
然后就迫不及待的学习了各种float[]转int[]的方法,对比一下它们的效率(其实我还是觉得C++更快,一个指针类型的转换,哦啦)
下面是我写的各种数组赋值转换的方法和结果的对比。
1.Marshal.Copy,有2个数组拷贝到IntPtr和IntPtr到数组【当T2不是Copy支持的类型时,会报错。引入动态dTo的原因是因为使用T2[] dTo无法编译],处理2000000*100字节1120.0018ms
public static T2[] Arr2Arr(T1[] from)
where T1: struct
where T2 :struct
{
int byteNum = from.Length * from[0].Sizeof();
T2 testByte = new T2();
dynamic dFrom = from;
dynamic dTo = new T2[byteNum / testByte.Sizeof()];
IntPtr ptr = Marshal.AllocHGlobal(byteNum);
Marshal.Copy(dFrom, 0, ptr, from.Length);
Marshal.Copy(ptr, dTo, 0, dTo.Length);
return dTo;
}
2.unsafe 方法使用指针获取IntPtr,减少一个副本,变得更快。【当T2不是Copy支持的类型时,会报错。引入 pFrom 的原因是泛型类型 T1[] 无法修复。它处理 2000000 *100 字节 695.9993ms
public unsafe static T2[] Arr2Arr(T1[] from, void * pFrom)
where T1 : struct
where T2 : struct
{
int byteNum = from.Length * from[0].Sizeof();
T2 testByte = new T2();
dynamic dTo = new T2[byteNum / testByte.Sizeof()];
IntPtr ptr = new IntPtr(pFrom);
Marshal.Copy(ptr, dTo, 0, dTo.Length);
return dTo;
}
3.通过GCHandle获取IntPtr,然后复制【T2不是Copy支持的类型时出错】,处理2000000*100字节930.0481ms
public static T2[] Arr2Arr2(T1[] from)
where T1 : struct
where T2 : struct
{
var gch = GCHandle.Alloc(from,GCHandleType.Pinned);
IntPtr ptr = gch.AddrOfPinnedObject();
int byteNum = from.Length * from[0].Sizeof();
T2 testByte = new T2();
dynamic dTo = new T2[byteNum / testByte.Sizeof()];
Marshal.Copy(ptr, dTo, 0, dTo.Length);
gch.Free();
return dTo;
}
4.Array.Copy方法,原生数组复制方法【无Copy,可以处理任何值类型】,处理2000000*100字节620.042ms
public static T2[] Arr2Arr3(T1[] from)
where T1 : struct
where T2 : struct
{
int byteNum = from.Length * from[0].Sizeof();
T2 testByte = new T2();
T2[] dTo = new T2[byteNum / testByte.Sizeof()];
Array.Copy(from, dTo, dTo.Length);
return dTo;
}
5. 通过Buffer.BlockCopy复制数组,最快,感觉和c++的memcpy类似【不用Copy,可以处理任何值类型】,处理2000000*100字节300.0329ms
public static T2[] Arr2Arr4(T1[] from)
where T1 : struct
where T2 : struct
{
int byteNum = from.Length * from[0].Sizeof();
T2 testByte = new T2();
T2[] dTo = new T2[byteNum / testByte.Sizeof()];
Buffer.BlockCopy(from, 0, dTo, 0, byteNum);
return dTo;
}
测试部分代码:
byte[] from = new byte[100];
from[0] = 1;
from[1] = 1;
var last = DateTime.Now;
for (int i = 0; i < 2000000; i++)
{
。。。
}
Console.WriteLine((DateTime.Now- last).TotalMilliseconds);
//sizeof扩展方法internal static class ExFunc
{
public static int Sizeof(this ValueType t)
{
return Marshal.SizeOf(t);
}
}
综上所述,Buffer.BlockCopy 是适用范围最广、效率最高的。
以上文章讲到C#中各种数组的直接数据拷贝/转换都是小编分享的内容,希望能给大家一个参考,也希望大家多多支持脚本之家。