Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a performance penalty in accessing the Windows API through Delphi?

Tags:

c++

winapi

delphi

I've had experience programming with ye old Win32 API in C++ several years ago, and recently I've been involved in development with Delphi. I immediately recognised a lot of the functions from the Windows API (e.g., CreateThread, CreateWindowEx, etc, etc).

I have found Embarcadero's documentation incomplete (to say the least), and typically refer to the Microsoft website for documentation. Where, might I add, all the functions are defined in C, which makes it difficult for the non-C folk out there (but easier for me).

What I want to know is - given that the Delphi function signatures are identical to the C function signatures provided by Microsoft - does a call to the Delphi Windows API function immediately call the Windows API function, or does it call an identical Delphi function which then calls the Windows API function and returns the result, the former meaning no distinguishable difference in performance compared to the corresponding C code, while the later meaning something of a performance penalty?

like image 421
magnus Avatar asked Feb 28 '14 06:02

magnus


2 Answers

Read the source. A call to CreateWindowEx is defined in the Windows.pas unit as a direct call to the CreateWindowExW function in User32.DLL (from XE5's source - similar definitions are found in all versions of Delphi for the supported OS versions):

function CreateWindowEx(dwExStyle: DWORD; lpClassName: LPCWSTR;
  lpWindowName: LPCWSTR; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
  hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
  stdcall; external user32 name 'CreateWindowExW';

So the answer to your specific question is no. There is no performance penalty. A call to a WinAPI function in Delphi does not incur a performance hit.

like image 169
Ken White Avatar answered Sep 20 '22 21:09

Ken White


Does a call to the Delphi Windows API function immediately call the Windows API function?

Not it does not.

For sake of argument let us consider a call to CloseHandle. This is declared in the Windows unit and implemented using external. When you call it, you do in fact call a function named CloseHandle in the Windows unit. So in pseudo assembler it looks like this:

.... prepare parameters
CALL     Windows.CloseHandle

Then, Windows.CloseHandle is implemented like this:

JMP      kernel32.CloseHandle

So, compared to a direct call, there is a call to a thunk function, and then a jump into the Win32 DLL. This is known as a trampoline.

It could be implemented differently. The compiler could emit code to call directly into the Win32 DLL. And some compilers will do this. For instance, the equivalent asm for this call as emitted by MSVC would be:

CALL     DWORD PTR [__imp__CloseHandle@4]

Here, __imp__CloseHandle@4 is the address of a location in memory which contains the address of CloseHandle in the Windows DLL. The loader writes the actual address of CloseHandle into __imp__CloseHandle@4 at load time.

Which is more efficient? Impossible to say for sure without profiling. But I'm confident that any difference will be significant in a vanishingly small number of cases.

Of course it is possible also for code to be generated that would call directly with no indirection. That would involve the loader patch every call to the function. That is probably a bad idea however because it would lead to a large number of load time fixups which would be a performance issue at startup. That said, it would be pretty much the same as a DLL that needs to be relocated at load time. In any case, I know of no tool chain that adopts this policy.

Perhaps what you are concerned about is whether these functions are the real Win32 functions. Or whether there is a layer around them that changes the meaning. These are the real Win32 functions. There is no Delphi documentation because these are Win32 functions. The Win32 documentation on MSDN is the authoritative source of documentation.

As many people have said, the Win32 functions are called with no intervening layer. So they are directly called in these sense that your parameters are passed un-modified to the API functions. But the calling mechanism is indirect in the sense that it uses a trampoline. Semantically there is no difference.

like image 8
David Heffernan Avatar answered Sep 21 '22 21:09

David Heffernan