我有一个非托管方法,执行时需要高CPU。可以说非托管呼叫自然会占用高CPU吗?
以下是代码:
public void ReadAt(long ulOffset, IntPtr pv, int cb, out UIntPtr pcbRead)
{
Marshal.Copy(buffer, 0, pv, bytesRead);
pcbRead = new UIntPtr((uint)bytesRead);
bytesRead = 0;
if (streamClosed)
buffer = null;
}
答案 0 :(得分:2)
不能概括这一点是不安全的。托管和非托管方法都需要执行代码所需的CPU。
当有人说非托管呼叫可能很昂贵时,通常意味着在托管和非托管之间切换的开销。只有在像大型图像上的逐像素处理这样的紧密循环中进行非托管调用时,此特定成本才有意义。
可以通过适当的属性删除非托管调用的一些开销,特别是可以将安全检查从每次调用移动到程序集加载时。当然,这已经为.NET框架中的所有非托管函数完成了。
关于你为什么在这个函数上花费这么多时间的最佳猜测(没有更多的上下文)是你要么(a)复制一个非常大的数组,要么(b)你经常在循环中调用该方法。
在第一种情况下,在Marshal.Copy的托管非托管之间切换的开销可以忽略不计,复制大内存块将始终使CPU饱和(即100%使用一个内核)。除了完全取消复制操作之外,您无能为力(根据您使用缓冲区的方式,可能会或可能不会这样做。)
如果您处于第二种情况并且阵列非常小,则可能值得切换到纯托管循环。但是如果不进行测量就不要这样做,很容易猜错,并且Marshal.Copy的非托管实现可以比托管JIT提供更多技巧来弥补开销。
PS:您可能想要阅读this - 高CPU使用率本身并不是坏事,计算机只是试图尽快完成工作。托管或非托管并不重要,如果您的使用率低于100%(每个核心),这只意味着您的计算机无事可做。