Statische Verknüpfung vs. dynamische Verknüpfung

399

Gibt es zwingende Leistungsgründe, in bestimmten Situationen statische Verknüpfungen gegenüber dynamischen Verknüpfungen zu wählen oder umgekehrt? Ich habe Folgendes gehört oder gelesen, aber ich weiß nicht genug über das Thema, um für seine Richtigkeit zu bürgen.

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

2) (1) ist nicht wahr, wenn ein Profiling-Compiler verwendet wird, der Profildaten zur Optimierung von Programm-Hotpaths verwendet, da der Compiler durch statische Verknüpfung sowohl Ihren Code als auch den Bibliothekscode optimieren kann. Mit der dynamischen Verknüpfung kann nur Ihr Code optimiert werden. Wenn die meiste Zeit damit verbracht wird, Bibliothekscode auszuführen, kann dies einen großen Unterschied machen. Ansonsten gilt (1) weiterhin.

Eloff
quelle
59
"Mit statischer Verknüpfung kann der Compiler den Bibliothekscode optimieren", aber nur, wenn er das auch kompiliert! Wenn Sie nur auf vorkompilierte Objektdateien verlinken, kann Ihr Compiler diese nicht optimieren.
3
Wenn das stimmt, dann haben Sie Recht, aber es gibt einige Fragen, wie wahr das bei modernen Compilern ist. Wenn jemand dies auf die eine oder andere Weise überprüfen kann, wäre das großartig.
Eloff
5
Mit einem Compiler, der zu nativem Code kompiliert wird (wie die meisten C / C ++ - Compiler), gibt es keine weitere Chance für die Codeoptimierung. Wenn der Code in eine Zwischensprache (wie .Net IL) kompiliert wird, wird der JIT-Compiler aufgerufen, wenn die Bibliothek geladen wird, um ihn in nativen Code zu kompilieren. Diese endgültige Kompilierung kann mit der Zeit immer besser werden, wenn sich der JIT-Compiler weiterentwickelt.
Tarydon
3
@Eloff: VS2008 macht genau das mit aktiviertem LTCG. (Die lib-Dateien werden jedoch riesig.) Ich habe damit herumgespielt und für jemanden, der daran interessiert ist, "was mein Compiler für mich tun kann", ist es geradezu erstaunlich.
Peterchen

Antworten:

348
  • Durch dynamische Verknüpfung kann der gesamte Ressourcenverbrauch reduziert werden (wenn mehr als ein Prozess dieselbe Bibliothek verwendet (einschließlich der Version in "derselben" natürlich)). Ich glaube, dies ist das Argument, das seine Präsenz in den meisten Umgebungen bestimmt. Hier umfassen "Ressourcen" Speicherplatz, RAM und Cache-Speicher. Wenn Ihr dynamischer Linker nicht ausreichend flexibel ist, besteht natürlich das Risiko einer DLL-Hölle .
  • Dynamische Verknüpfung bedeutet , dass Fehlerbehebungen und Upgrades Bibliotheken propagieren zu verbessern Ihr Produkt , ohne dass Sie etwas zu versenden.
  • Plugins erfordern immer eine dynamische Verknüpfung.
  • Statische Verknüpfung bedeutet, dass Sie wissen, dass der Code in sehr begrenzten Umgebungen ausgeführt wird (zu Beginn des Startvorgangs oder im Rettungsmodus).
  • Durch statische Verknüpfungen können Binärdateien einfacher an verschiedene Benutzerumgebungen verteilt werden (auf Kosten des Sendens eines größeren und ressourcenintensiveren Programms).
  • Statische Verknüpfungen können etwas schnellere Startzeiten ermöglichen , dies hängt jedoch in gewissem Maße sowohl von der Größe und Komplexität Ihres Programms als auch von den Details der Ladestrategie des Betriebssystems ab.

Einige Änderungen, um die sehr relevanten Vorschläge in die Kommentare und in andere Antworten aufzunehmen. Ich möchte darauf hinweisen, dass die Art und Weise, wie Sie damit umgehen, stark von der Umgebung abhängt, in der Sie ausgeführt werden möchten. Minimale eingebettete Systeme verfügen möglicherweise nicht über genügend Ressourcen, um dynamische Verknüpfungen zu unterstützen. Etwas größere kleine Systeme unterstützen möglicherweise die dynamische Verknüpfung, da ihr Speicher klein genug ist, um die RAM-Einsparungen durch die dynamische Verknüpfung sehr attraktiv zu machen. Ausgereifte Consumer-PCs verfügen, wie Mark bemerkt, über enorme Ressourcen, und Sie können sich wahrscheinlich von den praktischen Problemen in dieser Angelegenheit Gedanken machen lassen.


Um die Leistungs- und Effizienzprobleme anzugehen: Es kommt darauf an .

Klassischerweise erfordern dynamische Bibliotheken eine Art Klebeschicht, was häufig einen doppelten Versand oder eine zusätzliche Indirektionsebene bei der Funktionsadressierung bedeutet und ein wenig Geschwindigkeit kosten kann (aber ist die Funktionsaufrufzeit tatsächlich ein großer Teil Ihrer Laufzeit ???).

Wenn Sie jedoch mehrere Prozesse ausführen, die alle häufig dieselbe Bibliothek aufrufen, können Sie bei Verwendung der dynamischen Verknüpfung im Vergleich zur Verwendung der statischen Verknüpfung Cache-Zeilen speichern (und damit die Leistung verbessern). (Es sei denn, moderne Betriebssysteme sind intelligent genug, um identische Segmente in statisch verknüpften Binärdateien zu erkennen. Scheint schwierig, weiß jemand?)

Ein weiteres Problem: Ladezeit. Sie zahlen irgendwann die Ladekosten. Wann Sie diese Kosten bezahlen, hängt davon ab, wie das Betriebssystem funktioniert und welche Verknüpfung Sie verwenden. Vielleicht möchten Sie es lieber aufschieben, bis Sie wissen, dass Sie es brauchen.

Beachten Sie, dass die statische und dynamische Verknüpfung traditionell kein Optimierungsproblem darstellt, da beide eine separate Kompilierung bis hin zu Objektdateien umfassen. Dies ist jedoch nicht erforderlich: Ein Compiler kann im Prinzip "statische Bibliotheken" zunächst mit einem verdauten AST-Formular "kompilieren" und diese "verknüpfen", indem er diese ASTs zu den für den Hauptcode generierten hinzufügt, wodurch die globale Optimierung ermöglicht wird. Keines der von mir verwendeten Systeme tut dies, daher kann ich nicht beurteilen, wie gut es funktioniert.

Die Beantwortung von Leistungsfragen erfolgt immer durch Testen (und Verwenden einer Testumgebung, die der Bereitstellungsumgebung so ähnlich wie möglich ist).

dmckee --- Ex-Moderator Kätzchen
quelle
24
Der Ressourcenverbrauch ist im Grunde genommen der Code-Raum, der im Laufe der Zeit immer weniger ein Problem darstellt. Wenn 500 KB Bibliothek von 5 Prozessen gemeinsam genutzt werden, bedeutet dies eine Einsparung von 2 MB, was weniger als 0,1% von 3 GB RAM entspricht.
Mark Ransom
3
Wenn die Bibliothek auch dieselbe virtuelle Zuordnung verwendet (dieselbe physische und virtuelle Adresse in allen Prozessen), speichert eine dynamische Verbindung nicht auch TLB-Steckplätze in der MMU des Prozessors?
Zan Lynx
6
Ein dynamischer Link erleichtert auch das Aktualisieren von fehlerhaftem Bibliothekscode mit besseren Versionen.
Zan Lynx
89
@Zan Es macht es auch einfach, einer funktionierenden Version fehlerhaften Code hinzuzufügen.
6
"Plugins erfordern immer eine dynamische Verknüpfung." Das ist falsch Einige Plugin-Modelle wie die AudioUnits von Apple können das Plugin in einem separaten Prozess ausführen und IPC verwenden. Dies ist eine sicherere Alternative zur dynamischen Verknüpfung für Plugins (das Plugin kann den Host nicht zum Absturz bringen). Schlagen Sie vor, die Antwort auf "Plugins erfordern möglicherweise eine dynamische Verknüpfung" oder ähnliches zu aktualisieren.
Taylor
68

1) basiert auf der Tatsache, dass beim Aufrufen einer DLL-Funktion immer ein zusätzlicher indirekter Sprung verwendet wird. Heute ist dies normalerweise vernachlässigbar. Innerhalb der DLL gibt es etwas mehr Overhead auf i386-CPUs, da sie keinen positionsunabhängigen Code generieren können. Auf amd64 können Sprünge relativ zum Programmzähler sein, was eine enorme Verbesserung darstellt.

2) Das ist richtig. Mit Optimierungen, die sich an der Profilerstellung orientieren, können Sie normalerweise eine Leistung von 10 bis 15 Prozent erzielen. Jetzt, da die CPU-Geschwindigkeit an ihre Grenzen gestoßen ist, könnte es sich lohnen, dies zu tun.

Ich würde hinzufügen: (3) Der Linker kann Funktionen in einer cacheeffizienteren Gruppierung anordnen, so dass teure Fehlschläge auf Cache-Ebene minimiert werden. Dies kann 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 keine Eliminierung von totem Code durchgeführt werden kann. Je nach Sprache ist der DLL-Code möglicherweise auch nicht optimal. Virtuelle Funktionen sind immer virtuell, da der Compiler nicht weiß, ob ein Client sie überschreibt.

Wenn aus diesen Gründen keine DLLs wirklich benötigt werden, verwenden Sie einfach die statische Kompilierung.

BEARBEITEN (um den Kommentar zu beantworten, vom Benutzer unterstrichen)

Hier ist eine gute Ressource zum positionsunabhängigen Codeproblem http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

Wie bereits erläutert, verfügt x86 nicht über AFAIK für andere als 15-Bit-Sprungbereiche und nicht für bedingungslose Sprünge und Aufrufe. Aus diesem Grund waren Funktionen (von Generatoren) mit mehr als 32 KB schon immer ein Problem und benötigten eingebettete Trampoline.

Unter gängigen x86-Betriebssystemen wie Linux müssen Sie sich jedoch nicht darum kümmern, ob die .so / DLL-Datei nicht mit dem gccSwitch generiert wird -fpic(wodurch die Verwendung der indirekten Sprungtabellen erzwungen wird). Wenn Sie dies nicht tun, wird der Code einfach so repariert, wie ein normaler Linker ihn verschieben würde. Dabei wird das Codesegment jedoch nicht gemeinsam genutzt, und es muss eine vollständige Zuordnung des Codes von der Festplatte zum Speicher und Berühren des Codes vorgenommen werden, bevor er verwendet werden kann (Leeren der meisten Caches, Aufrufen von TLBs) usw. Es gab eine Zeit wenn dies als langsam angesehen wurde.

Sie hätten also keinen Nutzen mehr.

Ich kann mich nicht erinnern, welches Betriebssystem (Solaris oder FreeBSD) mir Probleme mit meinem Unix-Build-System bereitet hat, weil ich dies einfach nicht getan habe und mich gefragt habe, warum es abgestürzt ist, bis ich mich beworben -fPIChabe gcc.

Lothar
quelle
4
Ich mag diese Antwort, weil sie die einzige war, die die Punkte ansprach, die ich in der Frage angesprochen habe.
Eloff
Es wäre interessant, Referenzen zu diesen DLL-Techniken und einen Vergleich zwischen verschiedenen Betriebssystemen zu haben.
UncleZeiv
Scheint in Ordnung zu sein, aber die CPU-Geschwindigkeit hat definitiv nicht ihre Grenzen erreicht.
Aidiakapi
67

Die dynamische Verknüpfung ist der einzige praktische Weg, um einige Lizenzanforderungen wie die LGPL zu erfüllen .

Mark Ransom
quelle
17
Solange der Endbenutzer eine erneute Verknüpfung mit dem LGPL-Code herstellen kann (z. B. weil Sie Ihren Quellcode oder kompilierte Objektdateien mit Ihrer Software bereitstellen), ist die statische Verknüpfung in Ordnung . Wenn Ihre Software für den internen Gebrauch bestimmt ist (dh nur innerhalb Ihres Unternehmens verwendet und nicht verteilt werden darf), können Sie außerdem eine statische Verknüpfung herstellen. Dies würde beispielsweise für Serversoftware gelten, bei der der Server nicht verteilt ist.
JBentley
3
Versteh es nicht. Könnten Sie mir mehr Quellen geben (oder mehr ausarbeiten), um zu schätzen, was Sie geschrieben haben?
Baskaya
4
@Thorn siehe LGPL-Lizenz Abschnitt 4.d + e . Sie müssen entweder in einem Formular verteilen, in dem der Benutzer einen Link erstellen muss, oder eine gemeinsam genutzte (dynamische) Bibliothek verteilen.
Mark Ransom
46

Ich stimme den Punkten zu, die dnmckee erwähnt, plus:

  • Statisch verknüpfte Anwendungen sind möglicherweise einfacher bereitzustellen, da weniger oder keine zusätzlichen Dateiabhängigkeiten (.dll / .so) vorhanden sind, die Probleme verursachen können, wenn sie fehlen oder am falschen Ort installiert werden.
stakx - nicht mehr beitragen
quelle
6
Es ist erwähnenswert, dass der Go-Compiler von Google hauptsächlich aus diesem Grund nur statisch Binärdateien kompiliert.
Hut8
34

Ein Grund für einen statisch verknüpften Build besteht darin, zu überprüfen, ob die ausführbare Datei vollständig geschlossen ist, dh ob alle Symbolreferenzen korrekt aufgelöst werden.

Als Teil eines großen Systems, das mithilfe kontinuierlicher Integration erstellt und getestet wurde, wurden die nächtlichen Regressionstests mit einer statisch verknüpften Version der ausführbaren Dateien ausgeführt. Gelegentlich wurde festgestellt, dass ein Symbol nicht aufgelöst wurde und die statische Verknüpfung fehlschlug, obwohl die dynamisch verknüpfte ausführbare Datei erfolgreich verknüpft wurde.

Dies trat normalerweise auf, wenn Symbole, die tief in den gemeinsam genutzten Bibliotheken saßen, einen falsch geschriebenen Namen hatten und daher nicht statisch verknüpft wurden. Der dynamische Linker löst nicht alle Symbole vollständig auf, unabhängig von der Verwendung der Tiefen- oder Breitenevaluierung. Sie können also eine dynamisch verknüpfte ausführbare Datei erstellen, die nicht vollständig geschlossen ist.

Rob Wells
quelle
1
Sehr guter Punkt, ich habe kürzlich versucht, dies mit einem Code zu tun, den ich bei der Arbeit habe, aber das statische Kompilieren erwies sich als überraschend ärgerlich und ich habe einfach aufgegeben
UncleZeiv
21

1 / Ich war an Projekten beteiligt, bei denen die dynamische Verknüpfung mit der statischen Verknüpfung verglichen wurde und der Unterschied nicht klein genug war, um zur dynamischen Verknüpfung zu wechseln (ich war nicht Teil des Tests, ich kenne nur die Schlussfolgerung).

2 / Dynamische Verknüpfung ist häufig mit PIC verbunden (Positionsunabhängiger Code, Code, der abhängig von der Adresse, unter der er geladen wird, nicht geändert werden muss). Abhängig von der Architektur kann PIC eine weitere Verlangsamung mit sich bringen, ist jedoch erforderlich, um die gemeinsame Nutzung einer dynamisch verknüpften Bibliothek zwischen zwei ausführbaren Dateien (und sogar zwei Prozessen derselben ausführbaren Datei, wenn das Betriebssystem die Randomisierung der Ladeadresse als Sicherheitsmaßnahme verwendet) nutzen zu können. Ich bin nicht sicher, ob alle Betriebssysteme die beiden Konzepte trennen können, aber Solaris und Linux und ISTR auch HP-UX.

3 / Ich war an anderen Projekten beteiligt, bei denen dynamische Verknüpfungen für die Funktion "Einfacher Patch" verwendet wurden. Aber dieser "einfache Patch" macht die Verteilung von kleinen Fixes ein wenig einfacher und von komplizierten zu einem Alptraum für die Versionierung. Wir mussten oft alles pushen und Probleme beim Kunden nachverfolgen, weil die falsche Version ein Token war.

Mein Fazit ist, dass ich statische Verknüpfungen verwendet habe, mit Ausnahme von:

  • für Dinge wie Plugins, die von dynamischer Verknüpfung abhängen

  • wenn die Freigabe wichtig ist (große Bibliotheken, die von mehreren Prozessen gleichzeitig verwendet werden, wie C / C ++ - Laufzeit, GUI-Bibliotheken, ... die häufig unabhängig verwaltet werden und für die der ABI streng definiert ist)

Wenn man den "einfachen Patch" verwenden möchte, würde ich argumentieren, dass die Bibliotheken wie die großen Bibliotheken oben verwaltet werden müssen: Sie müssen nahezu unabhängig von einem definierten ABI sein, der nicht durch Fixes geändert werden darf.

Ein Programmierer
quelle
1
Einige Betriebssysteme für Nicht-PIC- oder teure PIC-Prozessoren bereiten dynamische Bibliotheken für das Laden an einer bestimmten Adresse im Speicher vor. Wenn dies möglich ist, ordnen sie jedem Prozess, der mit ihr verknüpft ist, einfach eine Kopie der Bibliothek zu. Das reduziert den Overhead von PIC erheblich. Zumindest OS X und einige Linux-Distributionen tun dies, bei Windows bin ich mir nicht sicher.
Andrew McGregor
Danke Andrew, ich wusste nicht, dass einige Linux-Distributionen dies verwenden. Haben Sie eine Referenz, der ich folgen kann, oder ein Schlüsselwort, nach dem ich suchen kann, um mehr zu erfahren? (FWIW Ich hatte gehört, dass Windows eine Variante davon macht, aber Windows ist zu weit außerhalb meiner Kompetenzzone, als dass ich es erwähnen könnte.)
AProgrammer
Ich denke, das Schlüsselwort, nach dem Sie suchen, ist "Prelink" - es bereitet eine Bibliothek darauf vor, schnell an einer bestimmten Adresse geladen zu werden, um den Programmstart zu beschleunigen.
Blaisorblade
20

Hier wird ausführlich über gemeinsam genutzte Bibliotheken unter Linux und die Auswirkungen auf die Leistung gesprochen.

nr
quelle
3
+1 für die Verknüpfung mit Dreppers DSO-Howto, das jeder lesen sollte, der unter Linux Bibliotheken erstellt.
Janneb
10

Auf Unix-ähnlichen Systemen kann die dynamische Verknüpfung es 'root' schwer machen, eine Anwendung mit den gemeinsam genutzten Bibliotheken zu verwenden, die an abgelegenen Orten installiert sind. Dies liegt daran, dass der dynamische Linker LD_LIBRARY_PATH oder dessen Äquivalent für Prozesse mit Root-Rechten im Allgemeinen nicht berücksichtigt. Manchmal spart eine statische Verknüpfung den Tag.

Alternativ muss der Installationsprozess die Bibliotheken lokalisieren. Dies kann jedoch dazu führen, dass mehrere Versionen der Software nicht gleichzeitig auf dem Computer vorhanden sind.

Jonathan Leffler
quelle
1
Der Punkt LD_LIBRARY_PATHist nicht gerade ein Hindernis für die Verwendung gemeinsam genutzter Bibliotheken, zumindest nicht in GNU / Linux. Wenn Sie beispielsweise die gemeinsam genutzten Bibliotheken ../lib/relativ zur Programmdatei im Verzeichnis ablegen, gibt die Linker-Option mit der GNU-Toolkette -rpath $ORIGIN/../liban, dass die Bibliothek von diesem relativen Speicherort aus durchsucht werden soll. Sie können die Anwendung dann problemlos zusammen mit allen zugehörigen gemeinsam genutzten Bibliotheken verschieben. Mit diesem Trick ist es auch kein Problem, mehrere Versionen der Anwendung und der Bibliotheken zu haben (vorausgesetzt, sie sind verwandt, wenn nicht, könnten Sie symbolische Links verwenden).
FooF
> für Prozesse mit Root-Rechten. Ich denke, Sie sprechen von Setuid-Programmen, die von Nicht-Root-Benutzern ausgeführt werden - ansonsten macht das keinen Sinn. Und eine Setuid-Binärdatei mit Bibliotheken an nicht standardmäßigen Speicherorten ist seltsam - aber da nur root diese Programme installieren kann, kann er sie auch /etc/ld.so.conffür diesen Fall bearbeiten .
Blaisorblade
10

Es ist wirklich ziemlich einfach. Wenn Sie Ihren Quellcode ändern, möchten Sie 10 Minuten warten, bis er erstellt wurde, oder 20 Sekunden? Zwanzig Sekunden sind alles, was ich ertragen kann. Darüber hinaus hole ich entweder das Schwert heraus oder denke darüber nach, wie ich es mithilfe einer separaten Zusammenstellung und Verknüpfung wieder in die Komfortzone bringen kann.

Hans Passant
quelle
1
Ich habe den Unterschied in der Kompilierungsgeschwindigkeit nicht wirklich gemessen, aber ich würde eine dynamische Verbindung herstellen, wenn sie wesentlich schneller wäre. Boost macht genug schlechte Dinge mit meinen Kompilierungszeiten, so wie es ist.
Eloff
9

Das beste Beispiel für eine dynamische Verknüpfung ist, wenn die Bibliothek von der verwendeten Hardware abhängig ist. In der Antike wurde die C-Mathematikbibliothek als dynamisch eingestuft, sodass jede Plattform alle Prozessorfunktionen nutzen kann, um sie zu optimieren.

Ein noch besseres Beispiel könnte OpenGL sein. OpenGl ist eine API, die von AMD und NVidia unterschiedlich implementiert wird. Und Sie können eine NVidia-Implementierung nicht auf einer AMD-Karte verwenden, da die Hardware unterschiedlich ist. Aus diesem Grund können Sie OpenGL nicht statisch mit Ihrem Programm verknüpfen. Hier wird die dynamische Verknüpfung verwendet, um die API für alle Plattformen zu optimieren.

Arne
quelle
8

Die dynamische Verknüpfung benötigt zusätzliche Zeit, damit das Betriebssystem die dynamische Bibliothek finden und laden kann. Mit der statischen Verknüpfung ist alles zusammen und es ist eine einmalige Belastung des Speichers.

Siehe auch DLL Hell . Dies ist das Szenario, in dem die vom Betriebssystem geladene DLL nicht die mit Ihrer Anwendung gelieferte oder die von Ihrer Anwendung erwartete Version ist.

Thomas Matthews
quelle
1
Es ist wichtig zu beachten, dass es eine Reihe von Gegenmaßnahmen gibt, um DLL Hell zu vermeiden.
ocodo
5

Ein weiteres Problem, das noch nicht besprochen wurde, ist das Beheben von Fehlern in der Bibliothek.

Bei der statischen Verknüpfung müssen Sie nicht nur die Bibliothek neu erstellen, sondern auch die ausführbare Datei neu verknüpfen und neu verteilen. Wenn die Bibliothek nur in einer ausführbaren Datei verwendet wird, ist dies möglicherweise kein Problem. Aber je mehr ausführbare Dateien neu verknüpft und neu verteilt werden müssen, desto größer ist der Schmerz.

Mit der dynamischen Verknüpfung erstellen Sie einfach die dynamische Bibliothek neu und verteilen sie, und fertig.

R Samuel Klatchko
quelle
2

Durch statische Verknüpfung erhalten Sie nur eine einzige Exe. Um eine Änderung vorzunehmen, müssen Sie Ihr gesamtes Programm neu kompilieren. Während Sie bei der dynamischen Verknüpfung nur Änderungen an der DLL vornehmen müssen und wenn Sie Ihre Exe ausführen, werden die Änderungen zur Laufzeit übernommen. Es ist einfacher, Aktualisierungen und Fehlerbehebungen durch dynamische Verknüpfung bereitzustellen (z. B. Windows).

Govardhan Murali
quelle
2

Es gibt eine große und zunehmende Anzahl von Systemen, bei denen eine extreme statische Verknüpfung enorme positive Auswirkungen auf Anwendungen und Systemleistung haben kann.

Ich beziehe mich auf sogenannte "eingebettete Systeme", von denen viele zunehmend Allzweckbetriebssysteme verwenden, und diese Systeme werden für alles Mögliche verwendet.

Ein äußerst häufiges Beispiel sind Geräte, die GNU / Linux-Systeme mit Busybox verwenden . Ich habe dies mit NetBSD auf die Spitze getrieben, indem ich ein bootfähiges i386 (32-Bit) -System-Image erstellt habe, das sowohl einen Kernel als auch dessen Root-Dateisystem enthält. Letzteres enthält eine einzelne statisch verknüpfte (by crunchgen) Binärdatei mit Hardlinks zu Alle Programme, die selbst alle (zuletzt 274) Standard-Systemprogramme mit vollem Funktionsumfang enthalten (die meisten außer der Toolchain), und es sind weniger als 20 Megabyte groß (und laufen wahrscheinlich sehr komfortabel in einem System mit nur 64 MB Speicher (selbst wenn das Root-Dateisystem unkomprimiert und vollständig im RAM ist), obwohl ich keinen gefunden habe, der so klein ist, um ihn zu testen).

In früheren Beiträgen wurde erwähnt, dass die Startzeit einer statisch verknüpften Binärdatei schneller ist (und viel schneller sein kann), dies ist jedoch nur ein Teil des Bildes, insbesondere wenn der gesamte Objektcode mit demselben verknüpft ist Datei, und insbesondere, wenn das Betriebssystem das Anforderungs-Paging von Code direkt aus der ausführbaren Datei unterstützt. In diesem idealen Szenario ist die Startzeit von Programmen buchstäblich vernachlässigbar, da sich fast alle Codeseiten bereits im Speicher befinden und von der Shell (und und) verwendet werdeninit allen anderen möglicherweise laufenden Hintergrundprozessen) verwendet werden, selbst wenn das angeforderte Programm dies nicht getan hat wurde seit dem Start ausgeführt, da möglicherweise nur eine Seite Speicher geladen werden muss, um die Laufzeitanforderungen des Programms zu erfüllen.

Das ist jedoch immer noch nicht die ganze Geschichte. Normalerweise erstelle und verwende ich auch die NetBSD-Betriebssysteminstallationen für meine vollständigen Entwicklungssysteme, indem ich alle Binärdateien statisch verknüpfe. Obwohl dies enorm viel mehr Speicherplatz beansprucht (~ 6,6 GB insgesamt für x86_64 mit allem, einschließlich Toolchain und statisch verknüpftem X11) (insbesondere wenn eine vollständige Debug-Symboltabelle für alle Programme verfügbar bleibt, weitere ~ 2,5 GB), bleibt das Ergebnis bestehen Läuft insgesamt schneller und benötigt für einige Aufgaben sogar weniger Speicher als ein typisches dynamisch verknüpftes System, das angeblich Bibliothekscodeseiten gemeinsam nutzt. Festplatte ist billig (sogar schnelle Festplatte), und Speicher zum Zwischenspeichern häufig verwendeter Festplattendateien ist ebenfalls relativ billig, CPU-Zyklen jedoch nichtld.so für jeden Prozess Start Kosten , die beginnen , jederDie Startzeit dauert Stunden und Stunden von CPU-Zyklen, bis Aufgaben ausgeführt werden, bei denen viele Prozesse gestartet werden müssen, insbesondere wenn dieselben Programme immer wieder verwendet werden, z. B. Compiler auf einem Entwicklungssystem. Statisch verknüpfte Toolchain-Programme können die Build-Zeiten für mehrere Systeme mit mehreren Architekturen für meine Systeme um Stunden reduzieren . Ich habe die Toolchain noch nicht in meine Single crunchgen-Ed-Binärdatei integriert, aber ich vermute, dass in diesem Fall aufgrund des Gewinns für den CPU-Cache mehr Stunden Bauzeit eingespart werden.

Greg A. Woods
quelle
2

Die statische Verknüpfung umfasst die Dateien, die das Programm in einer einzelnen ausführbaren Datei benötigt.

Dynamische Verknüpfung ist das, was Sie als üblich betrachten würden. Sie macht eine ausführbare Datei, für die weiterhin DLLs erforderlich sind und die sich im selben Verzeichnis befinden müssen (oder die DLLs könnten sich im Systemordner befinden).

(DLL = Dynamic Link Library)

Dynamisch verknüpfte ausführbare Dateien werden schneller kompiliert und sind nicht so ressourcenintensiv.

Nykal
quelle
0

Static linking ist ein Prozess in der Kompilierungszeit, bei dem ein verknüpfter Inhalt in die primäre Binärdatei kopiert wird und zu einer einzelnen Binärdatei wird.

Nachteile:

  • Die Kompilierungszeit ist länger
  • Ausgangsbinär ist größer

Dynamic linkingist ein Prozess zur Laufzeit, wenn ein verknüpfter Inhalt geladen wird. Diese Technik ermöglicht:

  • Aktualisieren Sie die verknüpfte Binärdatei, ohne eine primäre neu zu kompilieren, die die ABIStabilität erhöht. [Info]
  • eine einzelne freigegebene Kopie haben

Nachteile:

  • Startzeit ist langsamer (verknüpfter Inhalt sollte kopiert werden)
  • Linker-Fehler werden zur Laufzeit ausgelöst
yoAlex5
quelle