原生c++;从VB.net调用dll时运行较慢,而从native.exe调用dll时运行较慢 我在C++ C++中使用了一些代码来处理某个GB的文件。我把它编译成一个.exe,大约需要8分钟。但是我需要从VisualBasic.net接口调用它,所以我将它放在.dll中,并创建了一个c++/cli包装类来调用本机dll中的代码。托管代码和本机dll之间的唯一交互是调用启动处理的函数。令我惊讶的是,处理过程所用的时间几乎是.exe方法所用时间的两倍。我并不是VB.net的专家,所以可能有一些设置或一些我不知道的东西要看。欢迎任何意见。提前感谢。

原生c++;从VB.net调用dll时运行较慢,而从native.exe调用dll时运行较慢 我在C++ C++中使用了一些代码来处理某个GB的文件。我把它编译成一个.exe,大约需要8分钟。但是我需要从VisualBasic.net接口调用它,所以我将它放在.dll中,并创建了一个c++/cli包装类来调用本机dll中的代码。托管代码和本机dll之间的唯一交互是调用启动处理的函数。令我惊讶的是,处理过程所用的时间几乎是.exe方法所用时间的两倍。我并不是VB.net的专家,所以可能有一些设置或一些我不知道的东西要看。欢迎任何意见。提前感谢。,.net,c++,vb.net,dll,c++-cli,.net,C++,Vb.net,Dll,C++ Cli,在从“托管”代码到本机或“非托管”代码的通信中,.NET framework会增加一些开销 所以你在性能方面看到的是我在一般情况下所期望的。如果本机DLL做了更多的工作,我希望通信开销(效率损失)的百分比会更低。两个想法: 也许您使用发行版配置构建了.exe,但是.dll被设置为Debug。您有时会看到发布版本和调试版本之间的巨大差异,优化的代码会产生巨大的差异 < L> > P >如果你的VB.NET除了调用C++代码之外做任何事情,那么它可以在你的DLL消耗的上面添加CPU负载。在VB.n

在从“托管”代码到本机或“非托管”代码的通信中,.NET framework会增加一些开销

所以你在性能方面看到的是我在一般情况下所期望的。如果本机DLL做了更多的工作,我希望通信开销(效率损失)的百分比会更低。

两个想法:

  • 也许您使用发行版配置构建了.exe,但是.dll被设置为Debug。您有时会看到发布版本和调试版本之间的巨大差异,优化的代码会产生巨大的差异

  • < L> > P >如果你的VB.NET除了调用C++代码之外做任何事情,那么它可以在你的DLL消耗的上面添加CPU负载。在VB.net端进行的任何一种后台处理都可以解释这种差异。要比较苹果和苹果,您应该有一个命令行VB.net app w/o GUI,并有一行调用dll函数

    <> LI>

    如果上面没有帮助,我建议您创建一个与此相同的DLL链接的本地C++应用程序,并将其与本地EXE版本进行比较。如果C++和DLL版本执行与C++独立的EXE相同的操作,那么在VB.NET端必须有一些东西消耗额外的CPU。如果在另一方面,当从本地C++调用DLL时也会很慢,那么您应该在EXE与DLL的构建过程中查找差异,或者针对EXE与DLL模式的宏/条件编译的差异。


祝你好运。

C++/CLI包装器真的只是调用DLL函数,还是加载DLL本身,然后继续使用.NET进行管理?本机过程是获取自己的线程还是在.NET上下文中创建的线程?我的直觉是.NET正在做一些不必要的事情来管理对象、DLL或线程的生命周期


因此,我的建议是添加一个事件来指示DLL正在完成它所做的任何事情,从本机DLL启动一个新线程来运行该过程,并立即返回事件句柄。让您的.NET在适当的地方等待该句柄。

不太理解为什么从DotNet端调用的本机dll可以将处理时间增加一倍,除非您提供更多详细信息


但是,如果本机exe版本按预期工作,则可以从DotNet运行本机exe作为后台进程,通过命令行传递api参数。您甚至可以将exe的控制台输出重定向到基于DotNet的GUI

这很奇怪。我将查看TaskManager中的所有列,并比较这两个进程(工作集大小、页面错误等)。然后我将查看性能监视器并查看缓存管理器值。最后但并非最不重要的一点是,您可以尝试只读取文件而不写入,以查看时间花在哪里。

代码中发生了什么样的处理?你的EXE文件需要100%个处理器时间,还是你做了很多文件I/O?你把你的本地C++代码放到LIB或DLL中,并确保它与你的本地EXE/你的.NET包装器中使用的LIB完全相同吗?这是您应该首先尝试的。处理大型文件的代码几乎总是受到文件系统的限制。读取一个数十亿字节的文件需要一段时间,硬盘速度相当慢。重要的是文件是否在之前读取并因此缓存在文件系统缓存中,是否有足够的可用RAM允许文件放入缓存,以及文件碎片的严重程度。唯一安全的比较方法是使用相同的文件并从冷启动运行定时测试。代码读取文件,处理信息,创建几个临时文件,创建一些映像,然后完成。处理器运行在50%,小于30%英寸的.exe模式。@丹尼尔:您绝对确信在创建.NET包装器时,您没有最终编译C++代码到托管代码吗?或者您没有为.NET版本使用未优化的调试版本?按照我的理解,只有一个从托管代码到本机代码的调用。因此,通信开销很难解释从8分钟增加到几乎两倍的时间。没错,托管类只调用一次本机代码来启动处理。-1,您没有阅读问题描述。它清楚地写着“一次启动进程的呼吁”。我坚持我的回答。用户进程不会在Windows下不间断地运行,每次进程中断和恢复时,都必须保存和恢复线程堆栈。当您在.NET+封送处理的调用代码下面运行本机DLL代码时,还需要保存和恢复更多内容。这里有一个实验来验证这个想法:尝试增加用户进程运行的优先级。更少的干扰应该意味着更少的开销;这同样是错误的。Net没有对非托管代码施加任何安全性。这仍然在调用KERNEL32.DLL