I have the following setup:
What's unexpected:
Delphi command line application source code:
program DelphiCpplibraryCall;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Windows;
type
TWork = function(Count : Integer) : Integer; cdecl;
var
Handle : THandle;
Work : TWork;
Result : Integer;
Freq : Int64;
Start : Int64;
Stop : Int64;
begin
try
Handle := LoadLibraryEx('worker.dll', 0, LOAD_WITH_ALTERED_SEARCH_PATH);
Work := GetProcAddress(Handle, 'work');
QueryPerformanceFrequency(Freq);
QueryPerformanceCounter(Start);
Result := Work(500000);
QueryPerformanceCounter(Stop);
Writeln(Format('Result: %d Time: %.6f s', [Result, (Stop-Start) / Freq]));
FreeLibrary(Handle);
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
C dll source code:
#include "worker.h"
#include <unordered_map>
class Item
{
public:
Item(const int value = 0) : _value(value) {}
virtual ~Item(void) {}
private:
int _value;
};
int work(int count)
{
typedef std::unordered_map<int, Item> Values;
Values* values = new Values;
int k = 0;
for (size_t i = 0; i < count; i++)
{
(*values)[i] = Item(i);
k++;
}
delete values;
return k;
}
Delphi + C dll soure code: DelphiCpplibraryCall.zip
Runtime comparison:
For some reason the the Delphi Debugger seems to slow down the C dll function call a lot which makes debugging nearly impossible.
Has anyone a clue what could case this issue or how to avoid it? Many thanks.
Edit: I can confirm now that the described behavior is not restricted to the Delphi IDE and Debugger at all. This problem also happens if I:
This means that the C dll release build function execution time changes depending on whether there is a debugger attached or not.
I can also confirm that it is the deletion of the unordered_map (delete values;
) that takes that long as soon as there is a debugger present.
Debug from the DLL project Set breakpoints in the DLL project. Right-click the DLL project and choose Set as Startup Project. Make sure the Solutions Configuration field is set to Debug. Press F5, click the green Start arrow, or select Debug > Start Debugging.
Debugging delphi source files You need to go to "project->options->compiler" on this tab you need to check the "use debug DCUs". After that you need to build your project again and you can run your application. From now on breakpoints also stop in Delphi source files.
In the Visual Studio toolbar, make sure the configuration is set to Debug. To start debugging, select the profile name in the toolbar, such as <project profile name>, IIS Express, or <IIS profile name> in the toolbar, select Start Debugging from the Debug menu, or press F5.
If the delay comes from the delete
call then it may be the memory manager (malloc) that uses the Windows heap memory manager. The heap memory manager executes additional extensive checks when memory is released and a debugger is attached.
These additional checks can be disabled by setting the environment variable _NO_DEBUG_HEAP
to 1
(starts with an underscore).
You can do this in Delphi for a specific project under Project/Options.../Debugger/Environment Block
or you can add _NO_DEBUG_HEAP
to the user's environment block under Control Panel/System Properties/Advanced System Settings/Environment Variables/System Variables
so it works for all projects and all applications. But then you may need to logout to apply the changes or at least restart the IDE.
This appears to be an issue with the MSVC implementation of this STL container. Exactly the same behaviour can be seen when you use the Visual Studio debugger. The MSVC runtime is switching behaviour when it detects a debugger.
I've found the following links that relate to this issue:
A large part of the problem appears to be the performance when clearing the map. Simply remove the delete
line from your C++ code to see much improved performance.
I cannot find a viable work around to this problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With