结构体转换成对应的byte数组
2010-05-25 17:03
344 查看
最近看到一个帖子,问的是怎么把自己定义的结构体转换成对应的byte数组,一般来说,都会想到用Marshal类来完成这个功能,其实还有一个方法也可以,那就是利用unsafe代码。
先定义假想的一个值类型:
1 public static Action<T, Stream> ByLcg<T>()
2 where T : struct
3 {
4 DynamicMethod dm = new DynamicMethod(string.Empty, typeof(void),
5 new Type[] { typeof(T), typeof(Stream) }, typeof(T));
6 var il = dm.GetILGenerator();
7 var ptr = il.DeclareLocal(typeof(T).MakePointerType());
8 var i = il.DeclareLocal(typeof(int));
9
var loopCondition = il.DefineLabel();
var loopBegin = il.DefineLabel();
il.Emit(OpCodes.Ldarga_S, 0);
il.Emit(OpCodes.Conv_U);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Br_S, loopCondition);
il.MarkLabel(loopBegin);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ldind_U1);
il.Emit(OpCodes.Callvirt, typeof(Stream).GetMethod("WriteByte"));
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Stloc_1);
il.MarkLabel(loopCondition);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Sizeof, typeof(T));
il.Emit(OpCodes.Clt);
il.Emit(OpCodes.Brtrue_S, loopBegin);
il.Emit(OpCodes.Ret);
return (Action<T, Stream>)dm.CreateDelegate(typeof(Action<T, Stream>));
}
看看结果如何:136,713,142
真的这么强大吗?LCG本身的代价哪?可以把count修改成1,再次运行,得到的结果是:0,0,14
也可以看到在循环次数太少的情况下,获得的性能优势不足以弥补LCG本身的消耗,那么多少是临界点哪?
我的机器上,经过多次试验,发现21000时,Marshal方法和LCG方法的时间消耗相等,也就是说,当次数小于21000次是,Marshal占了上风,单是如果,超过21000次时,LCG带来的性能优势,就足以弥补代码生成的损失了。(当然,前提是生成的代码,以委托的方式被缓存下来)
如果,无论次数多少,都要求最高性能的话,那就只有用unsafe的方法,把每一个需要用到的结构体都写一遍了,就是用人力换速度。。。
先定义假想的一个值类型:
static void Main() { MyStruct s = new MyStruct(); s.Low = 5; s.Hi = 10; s.X = 1; const int count = 1000000; MemoryStream ms = new MemoryStream(); Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < count; i++) ByUnsafe(s, ms); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); ms = new MemoryStream(); GC.Collect(2); GC.WaitForPendingFinalizers(); sw.Reset(); sw.Start(); for (int i = 0; i < count; i++) ByMarshal(s, ms); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); ms = new MemoryStream(); GC.Collect(2); GC.WaitForPendingFinalizers(); sw.Reset(); sw.Start(); var d = ByLcg<MyStruct>(); for (int i = 0; i < count; i++) d(s, ms); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); }
1 public static Action<T, Stream> ByLcg<T>()
2 where T : struct
3 {
4 DynamicMethod dm = new DynamicMethod(string.Empty, typeof(void),
5 new Type[] { typeof(T), typeof(Stream) }, typeof(T));
6 var il = dm.GetILGenerator();
7 var ptr = il.DeclareLocal(typeof(T).MakePointerType());
8 var i = il.DeclareLocal(typeof(int));
9
var loopCondition = il.DefineLabel();
var loopBegin = il.DefineLabel();
il.Emit(OpCodes.Ldarga_S, 0);
il.Emit(OpCodes.Conv_U);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Br_S, loopCondition);
il.MarkLabel(loopBegin);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ldind_U1);
il.Emit(OpCodes.Callvirt, typeof(Stream).GetMethod("WriteByte"));
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Stloc_1);
il.MarkLabel(loopCondition);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Sizeof, typeof(T));
il.Emit(OpCodes.Clt);
il.Emit(OpCodes.Brtrue_S, loopBegin);
il.Emit(OpCodes.Ret);
return (Action<T, Stream>)dm.CreateDelegate(typeof(Action<T, Stream>));
}
看看结果如何:136,713,142
真的这么强大吗?LCG本身的代价哪?可以把count修改成1,再次运行,得到的结果是:0,0,14
也可以看到在循环次数太少的情况下,获得的性能优势不足以弥补LCG本身的消耗,那么多少是临界点哪?
我的机器上,经过多次试验,发现21000时,Marshal方法和LCG方法的时间消耗相等,也就是说,当次数小于21000次是,Marshal占了上风,单是如果,超过21000次时,LCG带来的性能优势,就足以弥补代码生成的损失了。(当然,前提是生成的代码,以委托的方式被缓存下来)
如果,无论次数多少,都要求最高性能的话,那就只有用unsafe的方法,把每一个需要用到的结构体都写一遍了,就是用人力换速度。。。
相关文章推荐
- 结构体转换成对应的byte数组
- 如何把结构体转换成对应的byte数组
- byte数组和结构体相互转换
- C#学习之byte数组与结构体之间的转换
- 将byte数组转换成对应的十六进制的字符串形式
- 结构体转换byte数组
- 二进制byte[]数组转换成对应十六进制字符串
- C#中byte数组与结构体之间的转换
- VC二进制byte数组转换成对应字符串
- NSData 与 NSString,Byte数组,UIImage 的相互转换
- java中short,int转换成byte数组及byte数组转换成short,int
- Java 基础类型转换byte数组, byte数组转换基础类型
- 【原创】从图像转换到byte[]数组的几种方法
- 结构体与字符数组相互转换
- image与byte数组的转换
- PHP实现INT型,SHORT型,STRING转换成BYTE数组
- 将byte[]数组数据转换为图片用于预览显示
- C#语言的Image和byte数组的互相转换
- java工具——数字,byte[]数组互相转换
- 如何将int类型数据转换成byte数组