2009-10-13 7 views
5

Ich habe eine C++ - Bibliothek, die viel größeren Code generiert, den ich wirklich für das, was es tut, erwarten würde. Aus weniger als 50 K Zeilen Quelle bekomme ich gemeinsame Objekte, die fast 4 MB sind und statische Archive 9 drücken. Dies ist problematisch, sowohl weil die Bibliothek binaries ziemlich groß sind, und viel schlimmer, sogar einfache Anwendungen, die dagegen verlinken, erhalten typischerweise 500 bis 1000 KB in Codegröße. Das Kompilieren der Bibliothek mit Flags wie -Os hilft zwar etwas, aber nicht wirklich sehr.Was sind einige Techniken oder Tools zum Profilieren übermäßiger Code-Größe in C/C++ - Anwendungen?

Ich habe auch mit GCCs -frepo-Befehl experimentiert (obwohl die gesamte Dokumentation, die ich gesehen habe, unter Linux collect2 doppelte Vorlagen zusammenführen würde) und explizite Template-Instantiierung auf Vorlagen, die "wahrscheinlich" viel zu duplizieren scheinen , aber in beiden Fällen keine wirkliche Wirkung. Natürlich sage ich "wahrscheinlich", weil blindes Raten wie bei jeder Art von Profilerstellung fast immer falsch ist.

Gibt es ein Tool, das es einfach macht, die Code-Größe zu profilieren, oder eine andere Möglichkeit, herauszufinden, was so viel Platz in Anspruch nimmt, oder allgemein andere Dinge, die ich ausprobieren sollte? Etwas, das unter Linux funktioniert, wäre ideal, aber ich nehme, was ich bekommen kann.

Antwort

7

Wenn Sie herausfinden möchten, was in Ihre ausführbare Datei geschrieben wird, fragen Sie Ihre Werkzeuge. Aktivieren Sie die Option --print-map (oder -M) des ld-Linkers, um eine Map-Datei zu erstellen, die anzeigt, was im Speicher abgelegt wurde und wo. Dies ist für das Beispiel mit statischer Verknüpfung möglicherweise informativer.

Wenn Sie ld nicht direkt, sondern nur über die gcc-Befehlszeile aufrufen, können Sie ld-spezifische Optionen an ld von der gcc-Befehlszeile übergeben, indem Sie ihnen -Wl, voranstellen.

+0

Es ist nicht "-W1", es ist '-Wl' –

+0

@FX - Danke für das Erkennen. Ich habe es behoben. –

1

Eine Methode, die sehr grob, aber sehr schnell ist, ist die Größe Ihrer Objektdateien zu betrachten. Nicht der gesamte Code in den Objektdateien wird in die endgültige Binärdatei kompiliert, daher kann es einige falsche positive Ergebnisse geben, aber es kann einen guten Eindruck davon vermitteln, wo die Hotspots sein werden. Sobald Sie die größten Objektdateien gefunden haben, können Sie sie mit Tools wie objdump und nm durchsuchen.

2

Unter Linux führt der Linker sicherlich mehrere Template-Instanziierungen zusammen.

Stellen Sie sicher, dass Sie keine Debug-Binärdateien messen (Debug-Informationen könnten mehr als 75% der endgültigen Binärgröße einnehmen).

Eine Technik zur Reduzierung der endgültigen Binärgröße besteht darin, mit -ffunction-sections und -fdata-sections zu kompilieren und dann mit -Wl,--gc-sections zu verknüpfen.

Noch größere Reduktion (wir haben 25% gesehen) ist möglich, wenn Sie Entwicklungsversion von [gold][1] (die neue ELF-only-Linker, ein Teil der binutils) verwenden, und einen Link mit -Wl,--icf

Eine weitere nützliche Technik ist Reduzieren der Menge der Symbole, die von Ihren gemeinsamen Bibliotheken "exportiert" werden (alles wird standardmäßig exportiert), entweder über __attribute__((visibility(...))), oder mithilfe von Linker-Skript. Details here (siehe "Exportkontrolle").