【问题标题】:Callback with PInvoke is very slow使用 PInvoke 回调非常慢
【发布时间】:2013-06-30 13:39:53
【问题描述】:

我在我的 C# 应用程序中使用本机/非托管 C++ DLL。我使用 PInvoke 在 C# 中调用本机函数来注册回调方法:

[DllImport("MyHook.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U1)] // necessary due to http://dotnet.dzone.com/articles/pinvoke-c-bool-return-values
private static extern bool InstallHook(CallbackPrototype callback);

private delegate int CallbackPrototype(byte* bytes, int size, int max);

// ...

var callback = new CallbackPrototype(MyCallback);
_callbackHandle = GCHandle.Alloc(callback);
var result = InstallHook(callback);

// somewhere when I'm removing the hook, I call _callbackHandle.Free();

然后,当事件发生时,本机 C++ DLL 调用我的回调。

private int MyCallback(byte* bytes, int size, int max)
{
    //var buffer = new byte[size]; // A
    //Marshal.Copy(new IntPtr(bytes), buffer, 0, size); // B

    //WrapperInstance.ParseBytes(buffer, 0, size); // C
    var x = 1 + 1; // D

    return size;
}

当所有内容都被注释掉时,它运行良好。如果我开始在回调中取消注释 A 行,它会变得非常缓慢。我注意到它是因为在关键时刻调用了回调。回调运行时持续时间长到我作为人类注意到它是不可接受的。

怎么会这样? size 参数仅从 1 到 100。最多只需要分配 100 个字节 - 对于当今的计算机来说很少。我需要改进以使回调的运行时间更快。有什么想法吗?

为了进一步测试,我添加了 D 行。这没有任何影响。

编辑:为了更详细的测试,我在创建类时分配了一个大缓冲区。所以 A 行不再在回调中。如果 B 行随后被注释掉,它突然又开始花费大量时间。这一定与托管代码/虚拟机有关。我希望有可能让它更快。

【问题讨论】:

  • 看到代码因删除昂贵的方法调用而变慢当然完全不直观。显然,您需要停止试错法并使用探查器收集证据
  • 你的回调会被调用无数次吗?
  • 它被称为大约。两秒一次。汉斯·帕桑特,如果我理解正确的话,你会误会一些事情。当我取消注释 A 行时,通话速度变慢。对不起,如果我弄错了,我的英语一点也不好。当我发现我的眼睛出现性能问题时,我不明白为什么需要使用分析器。
  • 你所报告的基本上是难以置信的。分配 100 个字节不需要时间。 Hans 正在对这行做出反应:如果 B 行随后被注释掉,它会突然又开始花费大量时间。 如果您想让这成为一个真正的问题,请为我们提供一种重现的方法。否则你必须自己解决。

标签: c# c++ callback pinvoke unmanaged


【解决方案1】:

您基本上所做的是将字节复制到缓冲区中,然后再解析它们。您可以一次性完成,如下所示:

        var bytes = ReadBytes(address, Marshal.SizeOf(typeof(T)), isRelative);

        fixed (byte* b = bytes)
            return (T) Marshal.PtrToStructure(new IntPtr(b), typeof (T));

我从我的内存库中获取了这个例子,我认为它会比你现在使用的代码快很多,假设你只尝试检索值类型。

【讨论】:

  • 什么是 readbytes 函数,我可以在内存流中使用它吗
猜你喜欢
  • 2013-12-14
  • 1970-01-01
  • 1970-01-01
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多