Frage

Gibt es zwingende Gründe Leistung statische Linken über eine dynamische Verbindung oder umgekehrt in bestimmten Situationen zu wählen? Ich habe gehört, oder die folgenden lesen, aber ich weiß nicht genug über das Thema für seine Richtigkeit zu garantieren.

1) Der Unterschied in der Laufzeitleistung zwischen statischer und dynamischer Verknüpfung Verknüpfung ist in der Regel vernachlässigbar.

2) (1) gilt nicht, wenn eine Profilierungs Compiler, dass Anwendungen Profildaten zu optimieren Programm hotpaths weil mit statischen Linken, der Compiler sowohl Ihren Code optimieren und die externe Bibliothek. Bei der dynamischen Verknüpfung kann nur der Code optimiert werden. Wenn die meiste Zeit Bibliothekscode ausgegeben wird, ausgeführt wird, kann dies einen großen Unterschied machen. Andernfalls (1) gilt nach wie vor.

War es hilfreich?

Lösung

  • Dynamische Verknüpfung reduzieren Gesamtressourcenverbrauch (wenn mehr als ein Prozess teilt die gleiche Bibliothek (einschließlich der Version in der "gleichen", natürlich)). Ich glaube, das ist das Argument, dass es seine Präsenz in den meisten Umgebungen antreibt. Hier „Ressourcen“ umfasst Speicherplatz, RAM und Cache-Speicher. Natürlich ist es, wenn Ihre dynamischen Linker nicht ausreichend flexibel ist ein Risiko von DLL Hölle .
  • Dynamische Verknüpfung bedeutet, dass Fehlerbehebungen und Upgrades für Bibliotheken propagieren verbessern Ihre Produkt, ohne dass Sie etwas zu versenden.
  • Plugins immer rufen Sie für dynamische Verknüpfung.
  • Static Verknüpfung bedeutet, dass Sie den Code kennt, kann laufen in sehr begrenzt Umgebungen (früh im Boot-Prozess, oder im Rettungsmodus).
  • Static Verknüpfung kann Binärdateien machen leichter zu verteilen , um diverse Benutzerumgebungen (auf Kosten der Entsendung eine größere und Ressourcen hungrig Programm).
  • Static Verknüpfung zuläßt etwas schnellere Inbetriebnahme Zeiten, aber das hängt zu einem gewissen Grad sowohl von der Größe und Komplexität des Programms und auf die Einzelheiten der Ladestrategie des OS.

Einige Änderungen, die sehr relevante Vorschläge in den Kommentaren schließen und in anderen Antworten. Ich möchte anmerken, dass die Art und Weise Sie auf diese brechen eine Menge auf, was Umwelt ab, die Sie planen zulaufen. Minimal eingebettete Systeme möglicherweise nicht genügend Ressourcen zur Unterstützung dynamische Verknüpfung haben. Etwas größer kleine Systeme können auch dynamische Verknüpfung unterstützen, denn ihr Gedächtnis klein genug ist, um die RAM-Einsparungen von dynamischer zu gestalten Verknüpfung sehr attraktiv. Blas- Consumer-PC hat, als Mark Notizen, enorme Ressourcen, und Sie können wahrscheinlich die Bequemlichkeit Fragen treiben Ihr Denken in dieser Sache lassen.


, um die Leistung und Effizienz Probleme zu lösen. es hängt

Classically, dynamische Bibliotheken erfordern eine gewisse Art von Klebstoffschicht, die oft bedeutet doppelte Versendung oder eine zusätzliche Schicht von Dereferenzierung in Funktion Adressierung und ein wenig Geschwindigkeit kosten kann (ist aber Funktion Zeit tatsächlich einen großen Teil Ihrer Laufzeit aufrufen ?? ?).

Wenn Sie jedoch mehrere Prozesse ausgeführt werden, die alle die gleiche Anruf Bibliothek viel, können Sie Speichern Cache-Zeilen am Ende (und damit zu gewinnen auf die Leistung ausgeführt wird), wenn eine dynamische Verwendung Verknüpfung relativ statische Linken zu verwenden. (Es sei denn, moderne Betriebssysteme sind intelligent genug, um identische Segmente in statisch gelinkte Binärdateien zu bemerken. Es scheint schwer, jemand wissen?)

Ein weiteres Thema: Ladezeit. Sie zahlen die Kosten zu einem bestimmten Zeitpunkt zu laden. Wenn Sie diese Kosten zahlen, hängt ab, wie das Betriebssystem als auch, was funktioniert die Verknüpfung Sie verwenden. Vielleicht würden Sie lieber zahlen es aufschieben, bis Sie wissen, dass Sie es brauchen.

Beachten Sie, dass statische-vs-dynamische Verknüpfung traditionell ist nicht eine Optimierung Problem, denn sie beinhalten sowohl getrennte Sammlung bis auf Objektdateien. Allerdings ist dies nicht erforderlich: ein Compiler kann im Prinzip „Übersetzen“ „statische Bibliotheken“ auf eine verdaute AST Form zunächst und „Link“, um sie durch diese Äste zu denen, der Zugabe für den Haupt-Code erzeugt, damit die globale Optimierung befähigt. Keines der Systeme, die ich tun diese, so kann ich nicht sagen, wie gut es funktioniert.

Der Weg zur Antwort Performance Fragen ist immer durch Testen (und eine Testumgebung so viel wie die Implementierungsumgebung wie möglich nutzen).

Andere Tipps

1) basiert auf der Tatsache, dass eine DLL-Funktion aufrufen immer einen zusätzlichen indirekten Sprung verwendet. Heute ist dies in der Regel vernachlässigbar. Innerhalb der DLL gibt es einige mehr Aufwand auf i386-CPU, weil sie nicht Position unabhängigen Code erzeugen kann. Auf amd64 kann springt auf den Programmzähler relativ sein, so ist dies eine enorme Verbesserung ist.

2) Das ist richtig. Mit Optimierungen durch Profilieren geführte können Sie in der Regel etwa 10 bis 15 Prozent mehr Leistung gewinnen. Nun, da die CPU-Geschwindigkeit an ihre Grenzen erreicht hat, könnte es sich lohnen, es zu tun.

Ich möchte hinzufügen: (3) der Linker kann Funktionen anordnen in einem Cache-effiziente Gruppierung, so dass teure Cache-Ebene Misses minimiert werden. Es könnte sich auch vor allem bewirken, um die Startzeit von Anwendungen (basierend auf den Ergebnissen i mit der Sonne C ++ Compiler gesehen haben)

Und vergessen Sie nicht, dass mit DLL keine Beseitigung von totem Code ist durchgeführt werden kann. Je nach Sprache, kann der DLL-Code nicht optimal entweder. Virtuelle Funktionen sind immer virtuell, da der Compiler nicht weiß, ob ein Kunde es überschrieben wird.

Aus diesen Gründen im Fall gibt es keine wirkliche Notwendigkeit für DLL, dann nur statische Kompilierung verwenden.

EDIT (Kommentar zu beantworten, durch Benutzer Strich)

Hier ist eine gute Ressource über die Position unabhängige Codeproblem http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

erklärt Als x86 ist sie AFAIK nicht für etwas anderes haben dann 15-Bit-Sprungbereiche und nicht für unbedingte Sprünge und Anrufe. Das ist, warum Funktionen (von Generatoren) mehr als 32K mit haben ein Problem und benötigt immer eingebettet Trampoline.

Aber auf populären x86-Betriebssystem wie Linux brauchen Sie nur nicht, ob die SO / DLL-Datei mit dem gcc Schalter -fpic (die erzwingt die Verwendung der indirekten Sprungtabellen) erzeugt Pflege nicht. Denn wenn Sie dies nicht tun, wird der Code wie ein normaler Linker befestigt wäre es zu verlegen. Aber während dies zu tun macht es das Codesegment nicht gemeinsam nutzbare und es würde eine vollständige Abbildung des Codes von der Festplatte in den Speicher benötigen und sie alle berühren, bevor sie verwendet werden kann (die meisten der Cache-Speicher leeren, schlagen TLB ist) etc. Es gab eine Zeit, wenn dies wurde langsam betrachtet ... zu langsam.

Sie würden also keinen Nutzen nicht mehr haben.

Ich erinnere mich nicht, was OS (Solaris oder FreeBSD) gab mir Probleme mit meinem Unix-Build-System, weil ich gerade dies nicht zu tun und fragte sich, warum es abgestürzt ist, bis ich -fPIC auf gcc angewendet.

Dynamische Verknüpfung ist die einzige praktische Möglichkeit, einige Lizenzanforderungen wie der LGPL gerecht zu werden .

Ich bin mit den Punkten dnmckee erwähnt plus:

  • Statisch gelinkte Anwendungen könnten einfacher sein, zu implementieren, da es weniger oder keine zusätzlichen Dateiabhängigkeiten (.dll / .so) das könnte zu Problemen führen, wenn sie fehlen oder an der falschen Stelle installiert.

Ein Grund eine statisch gelinkte Build zu tun ist, um sicherzustellen, dass Sie die volle Schließung für die ausführbare Datei haben, das heißt, dass alle Symbolreferenzen korrekt aufgelöst werden.

Als Teil eines großen Systems, die kontinuierliche Integration mit gebaut und getestet wurde, wurden die nächtlichen Regressionstests laufen eine statisch gelinkte Version der ausführbaren Dateien verwenden. Gelegentlich würden wir sehen, dass ein Symbol nicht lösen würde und die statische Verbindung fehlschlagen würde, obwohl die dynamisch verknüpfte ausführbar würde erfolgreich verknüpfen.

Dies wurde vorkommende in der Regel, wenn Symbole, die tief in den gemeinsam genutzten Bibliotheken saßen einen misspelt Namen haben und würde so nicht statisch Link. Der dynamische Linker nicht vollständig alle Symbole lösen, unabhängig davon, mit Tiefen ersten oder Breiten erste Auswertung, so dass Sie mit einer dynamisch verknüpften ausführbaren beenden können, die nicht vollständige Schließung hat.

1 / Ich habe an Projekten, in denen dynamische vs statische Linken Verknüpfung gebenchmarkt wurde und der Unterschied war nicht klein genug, um Schalter zu dynamisch bestimmt Verknüpfung (I nicht Teil des Tests war es, ich weiß nur zu dem Schluss)

2 / Dynamische Verknüpfung wird oft mit PIC (Position unabhängigen Code, Code, der muss nicht auf der Adresse abhängig modifiziert werden, bei dem es geladen wird) zugeordnet ist. Abhängig von der Architektur PIC kann eine andere Abschwächung bringen, sondern wird benötigt, um Nutzen zu erhalten, eine dynamisch verknüpfte Bibliothek zwischen zwei ausführbaren teilen (und sogar zwei Verfahren der gleichen ausführbaren wenn die OS Verwendung Randomisierung von Ladeadresse als Sicherheitsmaßnahme). Ich bin nicht sicher, dass alle OS erlauben, die beiden Konzepte zu trennen, aber Solaris und Linux zu tun und ISTR, dass HP-UX funktioniert auch.

3 / Ich habe an anderen Projekten gegeben, die dynamische Verknüpfung für die „easy-Patch“ -Funktion verwendet. Aber dieses „easy-Patch“ macht die Verteilung von kleinen fix ein wenig einfacher und komplizierter man eine Versionierung Alptraum. Wir sind am Ende oft auf, indem er alles schieben und Probleme vor Ort beim Kunden zu verfolgen, weil die falsche Version war Token.

Meine Schlussfolgerung ist, dass ich verwendet, um statisches würde die Verknüpfung ausgenommen:

  • für Dinge wie Plugins, die auf dynamische abhängen Verknüpfung

  • , wenn gemeinsame Nutzung wichtig ist (große Bibliotheken durch mehrere Prozesse zur gleichen Zeit wie C / C ++ Runtime verwendet, GUI-Bibliotheken, ... die unabhängig oft verwaltet und für die das ABI ist streng definiert)

Wenn man die „easy-Patch“ verwenden möchten, würde ich argumentieren, dass die Bibliotheken haben oben wie die großen Bibliotheken verwaltet werden: sie nahezu unabhängig sein müssen ABI mit einer definierten, die nicht durch Korrekturen geändert werden müssen <. / p>

Diese über gemeinsam genutzte Bibliotheken auf Linux und Auswirkungen auf die Leistung im Detail diskutieren.

Es ist ziemlich einfach, wirklich. Wenn Sie eine Änderung in Ihrem Quellcode machen, haben Sie 10 Minuten warten wollen es Sekunden zu bauen oder 20? Zwanzig Sekunden ist alles, was ich ertragen kann. Darüber hinaus erhalte ich entweder das Schwert aus oder anfangen, darüber nachzudenken, wie ich getrennte Sammlung verwenden kann und die Verknüpfung in die Komfortzone zu bringen.

Auf Unix-ähnliche Systemen dynamische Verknüpfung kann für ‚root‘ das Leben schwer machen, eine Anwendung mit den gemeinsamen genutzten Bibliotheken an Orten, out-of-the-Art und Weise installiert zu verwenden. Dies liegt daran, der dynamische Linker wird in der Regel nicht die Aufmerksamkeit auf LD_LIBRARY_PATH oder seine für Prozesse mit Root-Rechten gleichwertig zahlen. Manchmal, dann statisch Linke retten den Tag.

Alternativ kann der Installationsprozess hat die Bibliotheken zu finden, aber das kann es für mehrere Versionen der Software auf der Maschine koexistieren erschweren.

Dynamische Verknüpfung erfordert zusätzliche Zeit für das Betriebssystem die dynamische Bibliothek zu finden und laden. Mit statischen Linken ist, alles zusammen und es ist ein One-Shot-Last in den Speicher.

Auch finden Sie unter DLL-Hölle . Dies ist das Szenario, in dem die DLL, dass die OS Lasten sind nicht derjenige, der mit Ihrer Anwendung kam, oder die Version, dass Ihre Anwendung erwartet.

Die beste Beispiel für eine dynamische Verbindung ist, wenn die Bibliothek ist von der verwendeten Hardware abhängig. In der Antike wurde die C-Mathematik-Bibliothek entschieden, dynamisch zu sein, so dass jede Plattform, die alle Prozessorfunktionen optimieren verwenden kann.

Ein noch besseres Beispiel könnte OpenGL sein. OpenGl ist eine API, die unterschiedlich von AMD und NVidia umgesetzt wird. Und Sie sind nicht in der Lage eine NVidia Implementierung auf einer AMD-Karte zu verwenden, da die Hardware unterscheidet. Sie können OpenGL nicht statisch in Ihrem Programm verknüpfen, weil davon. Dynamische Verknüpfung wird hier verwendet, um die API für alle Plattformen optimiert werden zu können.

Ein weiteres Problem noch nicht diskutiert Fehler in der Bibliothek zu fixieren.

Mit statischen Linken, Sie nicht nur die Bibliothek neu erstellen müssen, sondern müssen die ausführbare Datei neu verknüpfen und redestribute. Wenn die Bibliothek nur in einer ausführbaren Datei verwendet wird, kann dies kein Problem sein. Aber je mehr ausführbaren Dateien, die Notwendigkeit, neu verknüpft und neu verteilt werden, desto größer ist der Schmerz.

Bei der dynamischen Verknüpfung, die Sie gerade wieder aufzubauen und die dynamische Bibliothek weitergeben und Sie sind fertig.

statische Linken gibt Ihnen nur eine einzige exe, inorder eine Änderung, die Sie neu kompilieren Ihr ganzes Programm vornehmen müssen. Während in der dynamischen Verknüpfung müssen Sie Änderung vornehmen nur für die dll und wenn Sie Ihre exe ausführen, würde die Änderungen bei runtime.Its aufgenommen einfaches Updates zur Verfügung zu stellen und Fehlerbehebung durch dynamische Verknüpfung. (ZB: Fenster)

Es gibt eine große und wachsende Zahl von Systemen, bei denen ein extremes Niveau der statischen Verknüpfung kann eine enorme positive Auswirkungen auf die Anwendungen und die Systemleistung haben.

Ich beziehe mich auf das, was oft als „eingebettete Systeme“ genannt, von denen viele heute zunehmend Allzweck- Betriebssysteme verwendet werden, und diese Systeme sind für alles Erdenkliche verwendet.

Ein sehr gängiges Beispiel sind Geräte mit GNU / Linux-Systeme mit Busybox . Ich habe dies mit NetBSD von einem bootfähigen i386 Aufbau (32-Bit-System) Bild, das umfasst sowohl einen Kernel und dessen Wurzeldateisystem, wobei die letztere die für alle Programme eine einzelne statische vernetzt (durch crunchgen) binäre mit hart Verknüpfungen enthält, dass selbst enthält all (auch bei der letzten Zählung 274) des Standard Full-Feature-Systemprogramme (die meisten mit Ausnahme der Werkzeugkette), und es ist weniger als 20 mega Bytes groß (und wahrscheinlich läuft sehr gut in einem System mit nur 64 MB Speicher (auch mit dem root-Dateisystem unkomprimiert und vollständig im RAM), obwohl ich nicht in der Lage gewesen, eine so klein zu finden, es auf) zu testen.

Es hat sich in früheren Beiträge erwähnt, dass die Anlaufzeit eines statischen gebundenen Binärdateien schneller ist (und es kann ein Los schneller sein), aber dass nur ein Teil des Bildes ist, vor allem, wenn alle Objektcode wird in die gleiche Datei verknüpft ist, und mehr noch insbesondere, wenn das Betriebssystem unterstützt Paging Code direkt von der ausführbaren Datei verlangen. In diesem idealen Szenario ist die Startzeit der Programme wörtlich vernachlässigbar, da fast alle Seiten Code wird bereits im Speicher sein und von der Shell in Gebrauch sein (und und init alle anderen Hintergrundprozesse, die möglicherweise ausgeführt werden) selbst wenn das angeforderte Programm nicht seitdem Boot läuft seit vielleicht nur eine Seite des Speichers geladen werden muß, um die Laufzeitanforderungen des Programms zu erfüllen.

Aber das ist noch nicht die ganze Geschichte. Ich baue auch in der Regel und verwenden Sie die NetBSD-Betriebssystem installiert für meine volle Entwicklungssysteme durch statische-Verknüpfung aller Binärdateien. Auch wenn dies nimmt eine enorme Menge mehr Speicherplatz (~ 6.6GB insgesamt für x86_64 mit allem, einschließlich Toolchain und X11 statisch-linked) nach wie vor, das Ergebnis (vor allem, wenn ein Symbol in voller Debug-Tabellen für alle Programme einer anderes ~ 2,5 GB hält) läuft insgesamt schneller und für einige Aufgaben verwendet auch weniger Speicher als ein typisches dynamisches gebundenes System, dass purports Bibliothek Code-Seiten zu teilen. Disk ist billig (auch schnelle Festplatte) und Speicher-Cache häufig verwendeten Dateien Platte ist auch relativ billig, aber CPU-Zyklen sind wirklich nicht, und für jeden Prozess der ld.so Start Kosten zahlen, die beginnen, alle Zeit werden immer und immer wieder, wie Compiler auf einem Entwicklungssystem startet wird von Aufgaben Stunden und Stunden der CPU-Zyklen nehmen, die viele Prozesse erfordern beginnen, vor allem, wenn die gleichen Programme verwendet. Static-Linked-Toolchain-Programme können für meine Systeme von Stunden Multi-Architektur Bauzeiten Voll OS reduzieren . Ich habe noch die Werkzeugkette in meine einzige crunchgen'ed binär zu bauen, aber ich vermute, wenn ich es tun wird, weil der Gewinn für den CPU-Cache mehr Stunden Aufbauzeit gespeichert werden.

Statische Verknüpfung enthält die Dateien, die das Programm Bedürfnisse in einer einzigen ausführbaren Datei.

Dynamische Verknüpfung ist das, was man die üblichen in Betracht ziehen würde, macht es eine ausführbare Datei, die noch DLLs und so erfordert im gleichen Verzeichnis zu sein (oder die DLLs im Systemordner sein könnten).

(DLL = Dynamic Link Bibliothek)

Dynamisch verknüpfte ausführbare Dateien kompiliert werden schneller und sind nicht als ressourcenlastig.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top