2012-10-14 17 views
12

Ich habe ein großes Problem. Ich habe eine gemeinsame Bibliothek, die überall in meinem Projekt verwendet wird. Diese Bibliothek verwendet intensiv boost.spirit und boost.fusion. Leider ist die Bibliothek ca. 700 MB groß. Alle boost.spirit -hoher Code wird verwendet und es funktioniert gut. Welche Schritte können unternommen werden, um die Ausgabegröße zu reduzieren? Gibt es ein Tool, mit dem Sie feststellen können, welche Template-Instanziierungen den größten Teil des Speicherplatzes verschwenden?Wie kann die Ausgabegröße von vorlagenintensivem C++ - Code reduziert werden?

Zuerst habe ich beschlossen, alle Geist-bewusst Code in CPP-Dateien zu verschieben. Zweitens werde ich verschiedene Compiler-Flags ausprobieren, um die Größe zu optimieren. Ich weiß nicht, was ich sonst tun soll.

Update (Details)

Ich verwende GNU Toolchain. Die riesige Bibliothek ist eigentlich eine statische Bibliothek. Ausführbare Datei, die diese 700 MB-Bibliothek verwendet, ist 200 MB groß. Mindestens die Hälfte des Codes befindet sich in * .h-Dateien. Einige boost.spirit Grammatiken (sehr Template schwere Sache) befindet sich auch in * .h-Dateien.

Prost!

Antwort

5

Umzug der Geist bewusst Code zu .cpp Dateien ist ein guter erster Schritt, es könnte jedoch unvollständig sein, wie Sie erwähnen, Geist Grammatik in Header-Dateien.

  1. Stellen Sie sicher, dass keine Grammatik/Regeln jemals außerhalb der Bibliothek exportiert werden. Wenn Sie die typischen include/src Verzeichnisse haben, dann verschieben Sie diese Dateien (auch wenn Header) in das Verzeichnis src.

  2. Markieren Sie alle diese Symbole als intern in der Bibliothek. Sie sollten nicht von außerhalb der Bibliothek zugänglich sein.Abhängig von Ihrem Compiler gibt es spezifische Pragmas/Attribute, bei gcc lookup visibility attribute: __attribute__ ((visibility ("internal"))). Dies hilft dem Compiler, sie entsprechend zu optimieren, insbesondere kann ein Compiler den Code einer Funktion auch dann ausgeben, wenn er ihn an einer bestimmten Aufrufstelle einfügt, nur für den Fall, dass diese Funktionsadresse genommen wird. Bei interner Sichtbarkeit kann es jedoch, da es weiß, dass der Code das Objekt nicht verlässt, die Funktion verlassen.

  3. Ich scheine eine Flagge zu erinnern identische Funktion Körper zu verschmelzen aber nicht wieder zu finden scheinen ...

+0

Vielen Dank für die Sichtbarkeit Attribut, weiß nicht darüber. – Lazin

2

Einige Vorschläge:

  • wo möglich, versuchen Sie die gleiche Vorlage instantiations (als einfaches und gekünstelt, zB zur Wiederverwendung, ein std::vector<int> und std::vector<float> würde die gleiche interne Struktur haben und beide können nur behandeln ihre Elementdaten als undurchsichtige 4-Byte-Blobs, also könnte man an die anderen delegieren und einfach als ein Wrapper handeln, der nur auf den richtigen Typ zurückwirft, so dass die Interna des Vektors nur für einen Typ instanziiert werden müssen, anstatt zwei.

  • versuchen Sie einen anderen Compiler. Einige Compiler verwenden identische Template-Instanziierungen, in denen sie die Semantik des Programms nicht beeinflussen, während andere eher konservativ sind.

  • behalten Sie genau im Auge, was aus der Bibliothek exportiert wird. Symbole, die nicht exportiert werden und intern nicht referenziert werden, können vom Linker entfernt werden. (Wenn Sie eine statische Bibliothek erstellen, tritt diese natürlich erst ein, wenn sie in eine ausführbare Datei eingebunden ist. Um die Größe der Bibliothek selbst zu reduzieren, können Sie stattdessen versuchen, eine dynamische Bibliothek zu erstellen.)

Aber letztendlich klingt es so, als ob Sie nur eine weniger Template-schwere Bibliothek verwenden müssen. (Oder einen einfachen Parser zu schreiben, als Sie im Moment haben)

+1

Eines der Probleme bei der Wiederverwendung von Template-Instanziierungen ist, dass normalerweise jede Funktion eine andere Adresse haben sollte, und das verhindert, dass verschiedene Funktionen miteinander verschmelzen, selbst wenn ihr ausführbarer Code anders ist. Ich denke nicht, dass VC++ sich sehr darum kümmert, aber im engeren Sinne ist diese Optimierung nur verfügbar, wenn der Compiler beweisen kann, dass die Adressen nicht innerhalb des Programms verwendet werden ... –

+0

@MatthieuM. Das stimmt, deshalb tun es nicht alle Compiler. Es ist im Allgemeinen eine ziemlich sichere Optimierung (Sie vergleichen Funktionsadressen nicht oft, und wenn Sie das tun, und ich vermute, dass es in den meisten Fällen ungültig ist, ist es ziemlich einfach für den Compiler, es zu erkennen) - aber es tut es Wunder für die ausführbare Größe der Vorlage schweren Code – jalf

4

--ffunction-sections jede Funktion in einem eigenen Segment setzen. Nicht nützlich für sich selbst, aber der Linker kann unbenutzte Abschnitte mit --gc-sections entfernen. Jetzt ohne --function-segments würde dies nur funktionieren, wenn eine gesamte Quelldatei ungenutzt wäre, d.h. mit einer wahnsinnigen Granularität.

Offensichtlich benötigen Sie das Sichtbarkeitsattribut, das von Matthieu erwähnt wird, sonst werden alle Funktionen in der Bibliothek aufgrund ihrer Sichtbarkeit "verwendet".

Verwandte Themen