Hallo zusammen,
ich möchte aus C# möglichst schnell unmanaged code (in einer C DLL) aufrufen. Im moment sehe ich da zwei Möglichkeiten:
a) ganz normal über p/invoke über static extern...
b) mit LoadLibrary und GetProcAddress die Adresse eines Funktionszeigers holen und diesen dann mit der Marshal Klasse in ein delegate umwandeln.
So rein vom Gefühl her würde ich sagen, dass der zweite Ansatz schneller ist, da man zu jedem Zeitpunkt ein delegate schon hat und man den nur aufrufen muss während bei der ersten Variante die DLL gegebenfalls noch geladen werden muss (wird sie sofort nach dem Funktionsaufruf wieder entladen?)
Seht ihr noch andere Möglichkeiten? Bei der aufzurufenden Funktion handelt es sich um eine PaintFunktion die eben recht oft (ohne Parametern und Rückgabewert) aufgerufen wird.
Danke und Grüße,
Mark
Hallo,
ich würde sagen Du entwickelst einfach mal zu testzwecken alle beiden Varianten und führst anschliessend Benchmarks durch, dann siehst Du was schneller ist (ich persönlich denke dass es Variante 2 sein wird)
Grüsse,
Egon
egrath's Blog: http://egonrath.eg.funpic.de/wordpress
Falls du so einen Benchmark durchführst bitte posten, wäre da selbst gespannt.
Mfg
Preli
Die Performance läßt sich auch noch steigern, indem man den Pinvoke-Deklaration mittels SuppressUnmanagedCodeSecurityAttribute auszeichnet. Damit verzichtet .NET einen StackTrace aufzubauen und auf SecurityAttribute zu prüfen. Allerdings wird das ganze dann unsafe Code.
Hallo,
ich hab mir grade einen Micro-Benchmark geschrieben der das ganze testet. Und ich bin überascht:* LoadLibrary, GetProcAddress und Marshall nach Delegate: Für 1.000.000 Calls 279 ms (Mit Über- und Rückgabewert: 294 ms)
Hätt ich ehrlich gesagt nicht gedacht. Anbei der Micro-Benchmark.
Grüsse,
Egon
egrath's Blog: http://egonrath.eg.funpic.de/wordpress
Hi Egon,
danke für Deine Ergebnisse! Sehr interessant!!
Also ist mal wieder der einfache Weg schneller 🙂
Gibt es eine Möglichkeit, zur Laufzeit den Modulnamen (DLL Namen) sowie Einsprungnamen zu setzen (wenn man mittels P/Invoke arbeitet) oder ist das eben der Preis für die Geschwindigkeit ?
Hallo,
out-of-the Box gibts so was nicht so weit ich weiss - Du könntest aber System.Reflection.Emit bemühen um dir zur Laufzeit was entsprechendes zusammen zu bauen.
Grüsse,
Egon
egrath's Blog: http://egonrath.eg.funpic.de/wordpress
Nur rein interessehalber:
Wie ruft man managed C++ Code am schnellsten auf?
Mir schien es am schnellsten wenn ich eine Verlinkung über Referenz meines Projekts auf das C++ Projekt zugreife und es normal wie jede andere Klasse aufrufe. Ist das richtig?
Ich glaub deswegen muss ich jetzt nicht unbedingt nen neuen Thread aufmachen 😉.
Ah, und noch was zum Thema, wäre es viel langsamer wenn ich eine Wrapper Klasse erstelle und diese wie oben geschrieben aufrufe?
wie jede andere Klasse aufrufe
Nichts anderes ist es.
Managed C++ oder C++/CLI generiert ja auch nur ein Assembly. Ist also so als ob du in einem Projekt C# und VB.Net mischst, da am ende immer IL-Code rauskommt solltest du die Dll ganz normal als Referenz anbinden schneller und kompatibler gehts wohl kaum...