Program runs slower when launched outside of Visua

2019-03-12 15:00发布

问题:

I'm noticing some strange behaviour regarding my program. I'm writing it in C++ using Visual Studio Professional 2013 Update 1 and it consists of an exe application that links against multiple DLLs and calls functions that are defined in those DLLs.

In my main program (which consists of several thousands of lines of code) I call a DLL function (let's call it DLLFunction() ) and I calculate the time taken by that call, like this:

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();

What I am noticing is that it takes a much longer time when launching it outside Visual Studio. For example:

Running it in debug within Visual Studio with debugger attached --> ~50 ms

Running it in release within Visual Studio with debugger attached ---> ~25 ms

Running it in release within Visual Studio without debugger attached ---> ~20 ms

Running it outside of Visual Studio (release build) ---> ~80 ms

As you can see running it in release outside of Visual Studio actually takes longer than running a debug build with a debugger attached!

The offending DLL is built within the same solution by the same compiler, and I've double checked that all DLLs in the directory from where I launch my application are the right ones.

What could be the reason of such a behaviour?

EDIT 5: The main application spawns another console application and communicates with it using named pipes. It turned out that not spawning that another application makes the DLL call fast outside Visual Studio.

However the same application is spawned both inside and outside Visual Studio, so i don't see why it slows down other calls just outside Visual Studio.

EDIT 4: It turned out that this slow behaviour appears only if i place the function call in some part of the code of my main program, so it must be a problem related to that. It's many lines, but i'll continue researching.

Thank you for suggestions anyway, they were useful to identificate the problem.

EDIT 3: Measurements with QueryPerfomanceCounter:

The CPU cycles measured inside Visual Studio (~50k) are half of those outside (~110k) (are those returned by QueryPerfomanceCounter() actual CPU cycles by the way?).

Dividing it by the frequency shows similar results to the std::chrono ones.

EDIT 2: I checked with process explorer as suggested, the DLLs loaded within VS and outside VS are identical.

EDIT 1: as requested, i tried this:

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();

And the results: Running it in release within Visual Studio with debugger attached ---> ~19 seconds

Running it outside of Visual Studio (release build) ---> ~40 seconds

回答1:

The DLL isn't loaded in the program until you call it the first time. If that function is very small, the program could be spending the majority of it's time just loading the DLL.
Try changing to this:

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();

This way, the loading time isn't considered.



回答2:

The offending code isn't loaded until you run it the first time, at which point it fetched the dll and loaded it into memory. Since you were running in Visual Studio, it's likely eager loading everything as soon as you start the debugger, negating that first-call overhead. Doing this prevents the code from needing the extra space for the loaded DLL until it's absolutely sure it's needed, and can save space and time if certain references never get called.

When testing for access times such as this, you should ALWAYS put such tests through a loop and run them many many times, since conditions such as these severely affect the first call, but not subsequent calls, and other conditions of the system (such as resources demanded by another process) can cause fluctuations you'll want to flatten out for a good test. Never trust the time on a single-instance execution.



回答3:

I also would try by removing the code optimizations. May be some inline function behavior is giving more performance in VS debugger.

Try optimizations are off, right click on your project -> Properties -> Configuration Properties -> C/C++ -> Optimization -> Optimization = Disabled.