C#各种数组直接的数据复制/转换
之前做Opengl程序,用的的C#的SharpGL这个库,里面有各种奇怪绑定的函数,比如原型为:
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,存在数组到IntPtr,IntPtr到数组的2次拷贝【当T2不是Copy支持的类型会出错,之所以引入dynamic dTo 是因为使用T2[] dTo 无法编译通过】,处理2000000*100字节1120.0018ms
public static T2[] Arr2Arr<T1, T2>(T1[] from)
where T1: struct
where T2 :struct
{ int byteNum = from.Length * from[].Sizeof();
T2 testByte = new T2(); dynamic dFrom = from;
dynamic dTo = new T2[byteNum / testByte.Sizeof()]; IntPtr ptr = Marshal.AllocHGlobal(byteNum);
Marshal.Copy(dFrom, , ptr, from.Length);
Marshal.Copy(ptr, dTo, , dTo.Length);
return dTo;
}
2.unsafe的方法,通过指针获得IntPtr,减少了一次复制,速度变快【当T2不是Copy支持的类型会出错,之所以引入pFrom是因为无法fixed泛型T1[]】,处理2000000*100字节695.9993ms
public unsafe static T2[] Arr2Arr<T1, T2>(T1[] from, void * pFrom)
where T1 : struct
where T2 : struct
{
int byteNum = from.Length * from[].Sizeof();
T2 testByte = new T2();
dynamic dTo = new T2[byteNum / testByte.Sizeof()]; IntPtr ptr = new IntPtr(pFrom);
Marshal.Copy(ptr, dTo, , dTo.Length);
return dTo;
}
3.通过GCHandle获得IntPtr,然后复制【当T2不是Copy支持的类型会出错】,处理2000000*100字节930.0481ms
public static T2[] Arr2Arr2<T1, T2>(T1[] from)
where T1 : struct
where T2 : struct
{
var gch = GCHandle.Alloc(from,GCHandleType.Pinned);
IntPtr ptr = gch.AddrOfPinnedObject(); int byteNum = from.Length * from[].Sizeof();
T2 testByte = new T2();
dynamic dTo = new T2[byteNum / testByte.Sizeof()];
Marshal.Copy(ptr, dTo, , dTo.Length);
gch.Free();
return dTo;
}
4.Array.Copy的方法,原生的数组复制方法【没有了Copy,可以处理任意值类型】,处理2000000*100字节620.042ms
public static T2[] Arr2Arr3<T1, T2>(T1[] from)
where T1 : struct
where T2 : struct
{
int byteNum = from.Length * from[].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, T2>(T1[] from)
where T1 : struct
where T2 : struct
{
int byteNum = from.Length * from[].Sizeof();
T2 testByte = new T2();
T2[] dTo = new T2[byteNum / testByte.Sizeof()]; Buffer.BlockCopy(from, , dTo, , byteNum); return dTo;
}
测试部分代码:
byte[] from = new byte[];
from[] = ;
from[] = ; var last = DateTime.Now;
for (int i = ; i < ; 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 适用场合最广泛,效率最高。
例子下载地址:http://files.cnblogs.com/files/chihirosan/Convert.zip
C#各种数组直接的数据复制/转换的更多相关文章
- 字节数组与String类型的转换
还是本着上篇文章的原则,只不过在Delphi中string有点特殊! 先了解一下Delphi中的string 1. string = AnsiString = 长字符串,理论上长度不受限制,但其实受限 ...
- JSONObject.fromObject(map)(JSON与JAVA数据的转换)
JSON与JAVA数据的转换(JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互.) 上一篇文章中有这么 ...
- 【转】java中byte数组与int类型的转换(两种方式)----不错
原文网址:http://blog.csdn.net/piaojun_pj/article/details/5903009 java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法, ...
- 转载:JSONObject.fromObject(map)(JSON与JAVA数据的转换)
转载网址:http://blog.sina.com.cn/s/blog_821025b70100wh6v.html JSON与JAVA数据的转换(JSON 即 JavaScript Object Na ...
- 一条sql解决.一张表的数据复制到另外一张表
如何把一个表的数组复制到一张表?也许很多人会把这个表查出来的数据再插入到另外一张表里面,这样很麻烦又要写代码逻辑去处理,其实一条sql语句就可以把一张表的数据复制到另外一张表,或者一张表的某一条数据复 ...
- 【delphi】Byte数组与String类型的转换
string string = AnsiString = 长字符串,理论上长度不受限制,但其实受限于最大寻址范围2的32次方=4G字节: 变量Str名字是一个指针,指向位于堆内存的字符序列,字符序列起 ...
- json 与其他数据 格式转换及json学习新得
jsonobject var a={"a","A"} 通过json都对象能很轻松的操作json数据 jsonString var a=" ...
- 日期类&&包装类&&System类&&Math类&&Arrays数组类&&大数据类
day 07 日期类 Date 构造函数 Date():返还当前日期. Date(long date):返还指定日期 date:时间戳--->距离1970年1月1日 零时的毫秒数 常用方法 日期 ...
- 零基础学习java------day14-----泛型,foreach,可变参数,数组和集合间的转换,Set,Map,
1.泛型(jdk1.5以后出现) https://www.cnblogs.com/lwbqqyumidi/p/3837629.html#!comments (1)为什么要用泛型? 限制集合,让它只能存 ...
随机推荐
- How do annotations work internally--转
原文地址:http://stackoverflow.com/questions/18189980/how-do-annotations-work-internally The first main d ...
- 赞!15个来自 CodePen 的酷炫 CSS 动画效果
CodePen 是一个在线的前端代码编辑和展示网站,能够编写代码并即时预览效果.你在上面可以在线分享自己的 Web 作品,也可以欣赏到世界各地的优秀开发者在网页中实现的各种令人惊奇的效果. 今天这篇文 ...
- iOS_UIImage_给图片添加水印
github地址: https://github.com/mancongiOS/UIImage.git UIImage的Category UIImage+ImageWaterPrint.h #impo ...
- JDK8 的 Lambda 表达式原理
JDK8 使用一行 Lambda 表达式可以代替先前用匿名类五六行代码所做的事情,那么它是怎么实现的呢?从所周知,匿名类会在编译的时候生成与宿主类带上 $1, $2 的类文件,如写在 TestLamb ...
- Windows Azure Web Site (17) Azure Web Site 固定公网IP地址
<Windows Azure Platform 系列文章目录> 在之前的文档中,笔者介绍了Azure Web Site是一个多租户的环境,每个部署单元有一个可以通过Internet访问的入 ...
- java设计模式(二)---工厂方法模式
2普通工厂方法模式 就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建. 2.1创建接口 /** * 发送接口 * Created by mrf on 2016/2/25. */ public ...
- 理解SQL Server是如何执行查询的 (1/3)
查询执行的总图: 根据总图的流程,详细说明每个部分: 1. 请求(Request) SQL Server是C/S架构的平台.与它交互的唯一方式就是发送包含数据库命令的请求.应用程序和数据库之前的通信协 ...
- Android Studio导入项目非常慢的解决办法
问题 Android Studio目前已经更新到2.0 Preview 6了,作为Google大力推崇的开发工具,相对于Eclipse ADT有着不可比拟的优势.然而在实际使用时,依然有不少不爽的地方 ...
- Fiddler使用AutoResponder进行本地文件和线上文件的映射
直入正题.. 刚刚想写篇总结,照常登上博客园添加新随笔,写了百来字发现有什么不对劲 编辑器去哪儿了... 心想重新登录应该就OK了吧,点击退出然后重新登录 按钮一直显示加载中...简直就没法登录嘛.. ...
- Lambda表达式演变
Lambda表达式是一种匿名函数. 演变步骤: 一般的方法委托 => 匿名函数委托 => Lambda表达式 Lambda表达式其实并不陌生,他的前生就是匿名函数,所以要谈La ...