Csharp/C#教程:检查类型是否为blittable的最快方法?分享


检查类型是否为blittable的最快方法?

在我的serialiser / deserialiser中,我有以下代码段:

if (element_type.IsValueType && collection_type.IsArray) { try { GCHandle h = GCHandle.Alloc(array_object, GCHandleType.Pinned); int arrayDataSize = Marshal.SizeOf(element_type) * c.Count; var array_data = new byte[arrayDataSize]; Marshal.Copy(h.AddrOfPinnedObject(), array_data, 0, arrayDataSize); h.Free(); WriteByteArray(array_data); return; } catch (ArgumentException) { //if the value type is not blittable, then we need to serialise each array item one at a time } } 

其目的是尝试以尽可能最有效的方式(即,仅将内容作为一堆字节)写入流中的值类型数组。

当类型是值类型但不是blittable时,问题就出现了,Alloc()失败了。 此时捕获exception并将控制权传递给处理数组的代码,就好像它由引用类型组成一样。

然而,由于我的应用程序中遇到的值类型的数量,这种检查(由于抛出和捕获我理解的非常慢的exception)被certificate是严重的瓶颈。 所以我想知道, 检查类型是否是blittable的最快方法是什么?

我正在使用generics类来缓存结果。 测试以相同的方式完成(尝试分配固定句柄)。

 public static class BlittableHelper { public static readonly bool IsBlittable; static BlittableHelper() { try { // Class test if (default(T) != null) { // Non-blittable types cannot allocate pinned handle GCHandle.Alloc(default(T), GCHandleType.Pinned).Free(); IsBlittable = true; } } catch { } } } 

当前的答案适用于提问者的情况,但根据规范,blittable值类型的数组本身也是blittable类型。 扩展Ondřej的方法有点,所以它考虑到这一点,也适用于引用类型:

 public static bool IsBlittable() { return IsBlittableCache.Value; } public static bool IsBlittable(Type type) { if(type.IsArray) { var elem = type.GetElementType(); return elem.IsValueType && IsBlittable(elem); } try{ object instance = FormatterServices.GetUninitializedObject(type); GCHandle.Alloc(instance, GCHandleType.Pinned).Free(); return true; }catch{ return false; } } private static class IsBlittableCache { public static readonly bool Value = IsBlittable(typeof(T)); } 

作为副作用,这会为string返回(尽管正确) false ,因为GetUninitializedObject无法创建它。 假设Alloc确实检查了不稳定性( string除外),这应该是可靠的。

@IllidanS4在此页面上出色的代码错误地为数组错误地返回false ,其中元素是blittable 格式化类型 ,这意味着数组也是blittable。 从这个例子开始,我解决了这个问题,并为一些error handling的案例添加了处理,例如:

我还补充说,为避免昂贵的Exception块做了一些更详尽的案例,并对我能想到的所有不同类型的unit testing进行了unit testing。

 public static bool IsBlittable(this Type T) { while (T.IsArray) T = T.GetElementType(); bool b; if (!((b = T.IsPrimitive || T.IsEnum) || T.IsAbstract || T.IsAutoLayout || T.IsGenericType)) try { GCHandle.Alloc(FormatterServices.GetUninitializedObject(T), GCHandleType.Pinned).Free(); b = true; } catch { } return b; } 

另一个答案的漂亮缓存机制应该按原样使用。

使用https://msdn.microsoft.com/en-us/library/system.type.islayoutsequential.aspx和https://msdn.microsoft.com/en-us/library/system.type.isexplicitlayout.aspx :

上述就是C#学习教程:检查类型是否为blittable的最快方法?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

 element_type.IsValueType && collection_type.IsArray && (element_type.IsLayoutSequential || element_type.IsExplicitLayout) 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/985013.html

(0)
上一篇 2021年12月20日
下一篇 2021年12月20日

精彩推荐