我注意到有关我程序的一些奇怪行为。我使用Visual Studio Professional 2013 Update 1在C ++中编写它,它由一个exe应用程序组成,该应用程序链接多个DLL并调用这些DLL中定义的函数。
在我的主程序(由几千行代码组成)中,我调用了一个DLL函数(让我们称之为DLLFunction()
)并计算该调用所用的时间,如下所示:
auto beginTime = std::chrono::high_resolution_clock::now();
DllFunction();
auto endTime = std::chrono::high_resolution_clock::now();
long long totalTime = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
我注意到在Visual Studio外部启动它需要更长的时间。例如:
在Visual Studio中的调试中运行它并附带调试器 - &gt; ~50 ms
在Visual Studio 中的发布中运行,并附带调试程序 ---&gt; ~25 ms
在Visual Studio 中的发布中运行它,不附带调试器 ---&gt; ~20 ms
在Visual Studio中运行外部(发布构建)---&gt; ~80 ms
正如您所看到的,在Visual Studio外部的发行版中运行它实际上比运行附加调试器的调试版本需要更长的时间!
相同的编译器在相同的解决方案中构建了有问题的DLL,并且我已经仔细检查了我启动应用程序的目录中的所有DLL是否正确。
这种行为可能是什么原因?
编辑5 : 主应用程序生成另一个控制台应用程序并使用命名管道与它通信。事实证明,没有产生另一个应用程序使得DLL在Visual Studio之外快速调用。
然而,在Visual Studio内部和外部生成相同的应用程序,所以我不明白为什么它会减慢Visual Studio外部的其他调用。
编辑4 : 事实证明,只有当我将函数调用放在我的主程序代码的某些部分时,才会出现这种缓慢的行为,因此它必然是与此相关的问题。这是很多行,但我会继续研究。
无论如何,感谢您的建议,它们对于识别问题非常有用。
编辑3 : 使用QueryPerfomanceCounter进行测量:
在Visual Studio中测量的CPU周期(~50k)是外部的一半(~110k)(顺便说一下,QueryPerfomanceCounter()返回的实际CPU周期是什么?)。
将其除以频率显示与std :: chrono相似的结果。
编辑2 : 我按照建议检查了进程资源管理器,在VS和VS外部加载的DLL是相同的。
编辑1 :根据要求,我试过了:
auto beginTime = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 1000; ++i)
{
DllFunction();
}
auto endTime = std::chrono::high_resolution_clock::now();
long long totalTime = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
结果如下:
在Visual Studio 中的发布中运行,并附带调试程序 ---&gt; ~19 seconds
在Visual Studio中运行外部(发布构建)---&gt; ~40 seconds
答案 0 :(得分:4)
在您第一次调用DLL之前,DLL尚未加载到程序中。如果该功能非常小,程序可能花费大部分时间来加载DLL 尝试改为:
DllFunction();
auto beginTime = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 1000; ++i)
{
DllFunction();
}
auto endTime = std::chrono::high_resolution_clock::now();
long long totalTime = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
这样,加载时间不予考虑。
答案 1 :(得分:3)
在您第一次运行它之前,不会加载有问题的代码,此时它会获取dll并将其加载到内存中。由于您在Visual Studio中运行,因此一旦启动调试器,它就可能会急切地加载所有内容,从而否定了第一次调用开销。这样做可以防止代码在加载DLL之前需要额外的空间,直到它确实需要它为止,并且如果某些引用永远不会被调用,则可以节省空间和时间。
当测试这样的访问时间时,你应该总是把这些测试放在一个循环中并多次运行它们,因为这些条件严重影响了第一次调用,但没有后续调用,以及系统的其他条件(例如,另一个过程所要求的资源)可能会导致您想要进行良好测试的波动。永远不要相信单实例执行的时间。
答案 2 :(得分:0)
我也会尝试删除代码优化。可能是某些内联函数行为在VS调试器中提供了更多性能。
尝试优化已关闭,右键单击您的项目 - &gt;属性 - &gt;配置属性 - &gt; C / C ++ - &gt;优化 - &gt;优化=已禁用。