管理到非管理开销

2024-01-11

在 .NET 中,有几个地方必须离开托管代码并进入非托管(也称为本机代码)领域。仅举几例:

  • 外部 DLL 函数
  • COM调用

总是有一些关于开销的评论从一个原因跳到另一个原因,我的问题是是否有人测量了正在发生的确切开销,并可以解释如何计算它。例如,也许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(使用前将#替换为@)

管理到非管理开销 的相关文章

随机推荐