Gibt es eine Leistungseinbuße beim Zugriff auf die Windows API über Delphi?

8

Ich habe schon einige Jahre Erfahrung in der Programmierung mit der alten Win32-API in C ++ gesammelt und seit kurzem bin ich an der Entwicklung von Delphi beteiligt. Ich erkannte sofort viele der Funktionen von der Windows-API (z. B. CreateThread , CreateWindowEx usw.).

Ich habe festgestellt, dass die Dokumentation von Embarcadero unvollständig ist (um es milde auszudrücken), und verweisen Sie zur Dokumentation auf die Microsoft-Website. Wo, ich möchte hinzufügen, sind alle Funktionen in C definiert, was es für Nicht-C-Leute da draußen schwieriger macht (aber einfacher für mich).

Was ich wissen möchte ist, dass die Delphi-Funktionssignaturen identisch mit den von Microsoft bereitgestellten C-Funktionssignaturen sind. Rufen Sie die Delphi-Windows-API-Funktion sofort auf, um die Windows-API-Funktion aufzurufen. Oder ruft es eine identische Delphi-Funktion auf, die dann die Windows-API-Funktion aufruft und das Ergebnis zurückgibt, wobei ersteres keinen unterscheidbaren Unterschied in der Leistung im Vergleich zum entsprechenden C-Code bedeutet, während das spätere etwas Leistung bedeutet Strafe?

    
magnus 28.02.2014, 06:25
quelle

2 Antworten

20

Lesen Sie die Quelle. Ein Aufruf von CreateWindowEx wird in der Unit Windows.pas als direkter Aufruf der Funktion CreateWindowExW in User32.DLL definiert (aus XE5-Quellen - ähnliche Definitionen finden sich in allen Versionen von Delphi für die unterstützten Betriebssystemversionen):

%Vor%

Also ist die Antwort auf Ihre spezifische Frage nein. Es gibt keine Leistungseinbußen. Ein Aufruf einer WinAPI-Funktion in Delphi führt nicht zu einem Leistungseinbruch.

    
Ken White 28.02.2014, 06:34
quelle
10
  

Ruft ein Aufruf der Delphi-Windows-API-Funktion sofort die Windows-API-Funktion auf?

Tut es nicht.

Aus Gründen des Arguments betrachten wir einen Aufruf von CloseHandle . Dies wird in der Unit Windows deklariert und mit external implementiert. Wenn Sie es aufrufen, rufen Sie tatsächlich eine Funktion namens CloseHandle in der Einheit Windows auf. Im Pseudo-Assembler sieht das so aus:

%Vor%

Dann wird Windows.CloseHandle wie folgt implementiert:

%Vor%

Im Vergleich zu einem direkten Aufruf gibt es also einen Aufruf an eine Thunk-Funktion und dann einen Sprung in die Win32-DLL. Dies ist bekannt als ein Trampolin.

Es könnte anders implementiert werden. Der Compiler könnte Code ausgeben, um direkt in die Win32-DLL aufzurufen. Und einige Compiler werden dies tun. Zum Beispiel wäre die äquivalente Asm für diesen Aufruf, wie von MSVC ausgegeben,:

%Vor%

Hier ist __imp__CloseHandle@4 die Adresse eines Speicherorts, der die Adresse von CloseHandle in der Windows DLL enthält. Der Loader schreibt die tatsächliche Adresse von CloseHandle in __imp__CloseHandle@4 zur Ladezeit.

Was ist effizienter? Ohne Profiling unmöglich zu sagen. Aber ich bin zuversichtlich, dass jeder Unterschied in einer verschwindend geringen Anzahl von Fällen signifikant sein wird.

Natürlich ist es auch möglich, dass Code erzeugt wird, der direkt ohne Indirection aufruft. Das würde bedeuten, dass der Ladeprogramm jeden Aufruf der Funktion patchte. Das ist jedoch wahrscheinlich eine schlechte Idee, da dies zu einer großen Anzahl von Ladezeitkorrekturen führen würde, was beim Start ein Leistungsproblem darstellen würde. Das heißt, es wäre so ziemlich das Gleiche wie eine DLL, die beim Laden verschoben werden muss. Auf jeden Fall kenne ich keine Werkzeugkette, die diese Richtlinie anwendet.

Vielleicht interessiert Sie, ob diese Funktionen die echten Win32-Funktionen sind. Oder ob es eine Schicht um sie herum gibt, die die Bedeutung ändert. Dies sind die echten Win32-Funktionen. Es gibt keine Delphi-Dokumentation, da dies Win32-Funktionen sind. Die Win32-Dokumentation auf MSDN ist die maßgebliche Dokumentationsquelle.

Wie viele Leute schon gesagt haben, werden die Win32-Funktionen ohne Zwischenebene aufgerufen. Sie werden also direkt in diesem Sinne aufgerufen, dass Ihre Parameter unverändert an die API-Funktionen übergeben werden. Der Aufrufmechanismus ist jedoch indirekt in dem Sinne, dass ein Trampolin verwendet wird. Semantisch gibt es keinen Unterschied.

    
David Heffernan 28.02.2014 07:25
quelle

Tags und Links