1) basiert auf der Tatsache, dass der Aufruf einer DLL-Funktion immer einen zusätzlichen indirekten Sprung erfordert. Heutzutage ist dies normalerweise vernachlässigbar. Innerhalb der DLL gibt es auf i386-CPUs etwas mehr Overhead, weil sie keinen positionsunabhängigen Code erzeugen können. Auf amd64 können Sprünge relativ zum Programmzähler erfolgen, was eine große Verbesserung darstellt.
2) Das ist richtig. Mit Optimierungen, die von der Profilerstellung geleitet werden, kann man in der Regel etwa 10-15 Prozent Leistung gewinnen. Jetzt, wo die CPU-Geschwindigkeit ihre Grenzen erreicht hat, könnte es sich lohnen, dies zu tun.
Ich würde hinzufügen: (3) der Linker kann Funktionen in einer cache-effizienteren Gruppierung anordnen, so dass teure Cache-Level-Misses minimiert werden. Dies könnte sich auch besonders auf die Startzeit von Anwendungen auswirken (basierend auf den Ergebnissen, die ich mit dem Sun C++ Compiler gesehen habe)
Und vergessen Sie nicht, dass mit DLLs kein toter Code beseitigt werden kann. Je nach Sprache kann der DLL-Code auch nicht optimal sein. Virtuelle Funktionen sind immer virtuell, da der Compiler nicht weiß, ob sie von einem Client überschrieben werden.
Aus diesen Gründen sollte man, wenn kein wirklicher Bedarf an DLLs besteht, nur die statische Kompilierung verwenden.
EDIT (zur Beantwortung des Kommentars, durch Unterstreichen des Benutzers)
Hier finden Sie eine gute Quelle für das Problem des positionsunabhängigen Codes http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/
Wie bereits erwähnt, gibt es sie bei x86 nur für 15-Bit-Sprungbereiche und nicht für unbedingte Sprünge und Aufrufe. Deshalb waren Funktionen (von Generatoren) mit mehr als 32K immer ein Problem und benötigten eingebettete Trampoline.
Aber auf gängigen x86-Betriebssystemen wie Linux müssen Sie sich nicht darum kümmern, ob die .so/DLL-Datei nicht mit dem gcc
Schalter -fpic
(was die Verwendung der indirekten Sprungtabellen erzwingt). Denn wenn Sie das nicht tun, wird der Code einfach so fixiert, wie ein normaler Linker ihn verschieben würde. Dadurch wird das Codesegment jedoch nicht gemeinsam nutzbar, und es wäre eine vollständige Abbildung des Codes von der Festplatte in den Speicher erforderlich, bevor er verwendet werden kann (Leeren der meisten Caches, Angreifen der TLBs) usw. Es gab eine Zeit, in der dies als langsam galt.
Sie würden also keinen Nutzen mehr haben.
Ich kann mich nicht daran erinnern, welches Betriebssystem (Solaris oder FreeBSD) mir Probleme mit meinem Unix-Build-System bereitet hat, denn ich habe das einfach nicht gemacht und mich gewundert, warum es abgestürzt ist, bis ich die -fPIC
a gcc
.