c# - 占用高 CPU 的非托管方法调用

标签 c# .net

我有一个非托管方法,执行时占用大量 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;
 }       

最佳答案

不,一概而论是不安全的。托管和非托管方法都使用它们执行代码所需的任何 CPU。

当有人说非托管调用可能很昂贵时,他们通常指的是在托管和非托管之间切换的开销。只有在像对大图像进行逐像素处理这样的紧密循环中进行非托管调用时,这种特殊成本才会产生影响。

一些非托管调用的开销可以通过适当的属性来消除,特别是可以将安全检查从每次调用转移到程序集加载时间。对于 .NET 框架中的所有非托管函数,这当然已经完成。

关于您为何在该函数上花费如此多时间的最佳猜测(没有更多上下文)是,您要么 (a) 复制一个非常大的数组,要么 (b) 您经常在循环中调用该方法。

在第一种情况下,Marshal.Copy 在托管-非托管之间切换的开销可以忽略不计,复制大内存块总是会使 CPU 饱和(即一个内核的 100% 使用率)。除了完全消除复制操作之外,您无能为力(这可能会也可能不会,具体取决于您如何使用缓冲区)。

如果您属于第二种情况并且数组非常小,则可能值得切换到纯托管循环。但是不要在没有测量的情况下执行此操作,这很容易猜错,并且 Marshal.Copy 的非托管实现可以比托管 JIT 提取更多技巧来弥补开销。

PS:您可能想阅读 this - 高 CPU 使用率本身并不是坏事,计算机只是试图尽快完成任务。托管或非托管无关紧要,如果您的使用率低于 100%(每核心),则仅表示您的计算机无事可做。

关于c# - 占用高 CPU 的非托管方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4524532/

相关文章:

c# - 将列表的总和作为变量并在运行时对其进行编辑

c# - 我的手机有前置摄像头和/或麦克风吗?

c# - 在 4 中使用 3.5 组件

c# - 数据契约(Contract)异常。无法序列化

c# - 动态类型列表

C# .NET (WPF,DIGITALOCEAN) 创建 mysql 连接时现有数据库未知

c# - 如何从 *.dll 中检索所有公共(public)方法

c# - 这个变量在使用后会被释放吗?

c# - CLR 中一维和二维数组的最大大小

c# - 使用 Linq 根据 Values 自定义对象的属性过滤 Hashtable