在 .NET 中,有几个地方必须离开托管代码并进入非托管(也称为本机代码)领域。仅举几例:
总是有一些关于开销的评论从一个原因跳到另一个原因,我的问题是是否有人测量了正在发生的确切开销,并可以解释如何计算它。例如,也许byte[]
可以转换为IntPtr
甚至到byte*
在 .NET 中并帮助编组器节省一些 CPU 周期。
获取托管数组的地址确实是可能的。
首先,您必须使用固定阵列System.Runtime.InteropServices.GCHandle http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.aspx,这样垃圾收集器就不会移动数组。只要非托管代码可以访问托管数组,就必须保持分配的句柄。
byte[] the_array = ... ;
GCHandle pin = GCHandle.Alloc(the_array, GCHandleType.Pinned);
然后,您应该能够使用System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.unsafeaddrofpinnedarrayelement.aspx获取数组中任意元素的 IntPtr。
IntPtr p = Marshal.UnsafeAddrOfPinnedArrayElement(the_array,0);
重要的:固定对象会严重扰乱 GC 操作。能够在堆中移动对象是现代 GC 能够(在某种程度上)跟上手动内存管理的原因之一。通过将对象固定在托管堆中,GC 失去了相对于手动内存管理的性能优势:相对未碎片化的堆。
因此,如果您计划将这些数组保留在“非托管端”一段时间,请考虑制作该数组的副本。复制内存的速度快得惊人。使用Marshal.Copy(*)
从托管内存复制到非托管内存的方法,反之亦然。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)