15 Stimmen

Gibt es einen "Funktionsgrößen-Profiler"?

Nach drei Jahren Arbeit an einem C++-Projekt ist die ausführbare Datei auf 4 MB angewachsen. Ich würde gerne sehen, wohin dieser ganze Platz geht. Gibt es ein Tool, das die größten Platzfresser auflistet? Es wäre schön, die Größe nach Klasse (alle Funktionen in einer Klasse), nach Vorlage (alle Instanziierungen) und nach Bibliothek (wie viel gehört zur C-Standardbibliothek und zur STL? wie viel für jede Bibliothek in der Exe) zu sehen.

Bearbeiten: Hinweis: Ich verwende Visual C++ unter Windows.

0 Stimmen

Für den Fall, dass sich jemand wundert, stellte sich heraus, dass Flite (eine Text-to-Speech-Engine) mit 1,8 MB IIRC die bei weitem größte Komponente der 4 MB war, was ich durch Entfernen herausfand.

19voto

Todd Gamblin Punkte 56250

Unter Linux können Sie verwenden nm um alle Symbole in der ausführbaren Datei anzuzeigen und sie in umgekehrter Reihenfolge nach Größe zu sortieren:

$ nm -CSr --size-sort <exe>

Optionen:

  • -C entschlüsselt C++-Namen.
  • -S zeigt die Größe der Symbole an.
  • --size-sort sortiert die Symbole nach Größe.
  • -r kehrt die Sorte um.

Wenn Sie die Ergebnisse pro Namespace oder pro Klasse erhalten möchten, können Sie einfach grep die Ausgabe für ' namespace:: ', ' namespace::class_name:: ', usw. .

Wenn Sie nur Symbole sehen wollen, die definiert sind in die ausführbare Datei (nicht die, die anderswo definiert sind, wie in Bibliotheken), dann fügen Sie --defined-only . Die Sortierung nach Größe sollte das Problem jedoch lösen, da undefinierte Symbole keine Größe haben werden.

Für Windows sollten Sie immer noch in der Lage sein, die nm für Ihre Binärdateien, da nm unterstützt COFF Binärdateien. Sie können installieren nm über Cygwin, oder Sie könnten Ihre Windows-Datei auf einen Linux-Rechner kopieren und dort nm darauf.

Sie könnten auch versuchen dumpbin das Informationen über eine Binärdatei unter Windows ausgibt. Sie können Informationen über Symbole mit dem /SYMBOLS Schalter, aber es sieht nicht so aus, als ob er direkt Informationen über ihre Größe liefert.

0 Stimmen

Sie könnten es mit gcc unter Cygwin kompilieren und dann das nm-Tool verwenden, um eine ungefähre Liste zu erhalten.

1 Stimmen

Soweit ich weiß, unterstützt nm die COFF. Sie könnten es einfach über Cygwin installieren, oder Sie könnten die Exe auf einen Linux-Rechner kopieren und nm dort ausführen. Sie könnten auch das Windows-Dienstprogramm dumpbin ausprobieren. Siehe hier: support.microsoft.com/?id=121460

0 Stimmen

Ich glaube nicht, dass Sie Ihre Exe mit gcc kompilieren müssen, um sie mit nm zu verwenden. Alles, was nm tut, ist das Lesen des Binärformats.

7voto

Crashworks Punkte 39230

Unter Windows, wo Visual Studio kompiliert, befinden sich diese Informationen in der .map-Datei (in der Nähe der .pdb-Datei).

HINZUFÜGEN : Um die dekorierten Namen in der .map-Datei in etwas besser lesbares umzuwandeln, können Sie die undname.exe Dienstprogramm, das in Visual Studio enthalten ist. Es akzeptiert individuelle Namen auf der Befehlszeile oder Sie können es mit einer .map-Datei füttern.

Zum Beispiel,

Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of "?push_back@?$mini_vector@U?$Point@U?$FixedPoint@$0O@H@Math@@@Math@@$05@@QAAXABU?$Point@U?$FixedPoint@$0O@H@Math@@@Math@@@Z" is 

"public: void __cdecl mini_vector<struct Math::Point<struct Math::FixedPoint<14,int> >,6>::push_back(struct Math::Point<struct Math::FixedPoint<14,int> > const &)"

2 Stimmen

Ich schaue auf meine Map-Datei, und nicht wirklich sehen, wie Zeilen wie "0001:0000f380 ?push_back@?$mini_vector@U?$Point@U?$FixedPoint@$0O@H@Math@@@Math@@$05@@QAAXABU?$Point@U?$FixedPoint@$0O@H@Math@@@Math@@@Z 10010380 f i dibitmapsce:DIBitmap.obj" sind nützlich für die Profilerstellung.

0 Stimmen

Lassen Sie sich nicht von den unvollständigen Namen abschrecken. Dort steht, dass es in der geräteunabhängigen Bitmap-Unterstützung eine Funktion zum Anhängen an das Ende eines Punktvektors gibt, und zwar an der Adresse F380 (62336) im Segment 1. Ich wette, es gibt noch eine Menge solcher Funktionen. Schauen Sie nach, wo auf diese Funktion verwiesen wird, und wenn sie nicht benötigt wird, versuchen Sie, sie loszuwerden.

0 Stimmen

Sie können Namen mit undname.exe aus dem Verzeichnis Visual Studio bins entfernen; wenn Sie die Verknüpfung "Visual Studio 200X Command Prompt" ausführen, wird sie in Ihren %PATH% aufgenommen. Oder wenn Sie sie in Massen machen wollen, habe ich dieses Python-Skript gefunden, das dies automatisch tut: holycall.tistory.com/entry/

2voto

Mike Dunlavey Punkte 39339

Holen Sie sich eine Link-Map, oder verwenden Sie dumpbin um eine Liste der Symbole und Größen zu erhalten.

Wahrscheinlich werden viele Dinge hineingezogen, die Sie nicht unbedingt brauchen.

ADDED: Haben Sie eine zufriedenstellende Antwort erhalten? Mir ist klar, dass es zwei Arten gibt, wie Menschen an solche Probleme herangehen:

  • Nehmen Sie Messungen vor, bevor sie etwas tun.
  • Finden Sie einfach etwas Großes, das sie nicht brauchen, reißen Sie es heraus und wiederholen Sie es, bis sie es nicht mehr können.

Ich persönlich bevorzuge Letzteres, weil ich damit schneller zu Ergebnissen komme.

Sie sagen, die App sei 4 MB groß. Nehmen wir an, die tatsächliche erforderliche Größe beträgt 1 MB (oder eine andere Größe). Das bedeutet, wenn Sie eine Routine zufällig aus der Map-Datei auswählen, ist die Wahrscheinlichkeit, dass es sich um etwas handelt, das Sie nicht benötigen, 75 %. Finden Sie heraus, was der Grund dafür ist, dass sie enthalten ist, und prüfen Sie, ob Sie sie wirklich brauchen.

In dem von Ihnen genannten Beispiel haben Sie eine Klasse gesehen, die geräteunabhängige Bitmaps umschließt. Sie könnten Instanzen dieser Klasse in Ihrer Anwendung finden und sie möglicherweise durch einfache WIN32-Bitmaps ersetzen. Es wäre weniger schön, aber sparen Unmengen von app Größe.

Dann machen Sie weiter. Jedes große Stück, das Sie loswerden, führt dazu, dass die verbleibenden Stücke einen größeren Anteil der App einnehmen, weil die App geschrumpft ist, die Stücke aber nicht. Das macht es einfacher, sie in der Map-Datei zu finden.

0 Stimmen

Um noch einmal das Beispiel des DIB-Wrappers aufzugreifen: Diese Klasse könnte winzig sein und ich könnte nichts sparen, wenn ich sie herausnehme. OTOH, vielleicht gibt es viele verschiedene Instanzen von vector<T>, map<K,V>, hash_map, etc. und vielleicht würde ich Platz sparen, indem ich Wege finde, Instanzen zu teilen. Andererseits ist der Compiler vielleicht schlau genug, um identische Suproutinen zusammenzuführen (was bei Templates wahrscheinlich oft passiert), oder vielleicht nehmen diese Klassen trotz vieler Instanzen nicht so viel Platz ein. Wenn ich gute Daten hätte, würde sich vielleicht herausstellen, dass ich nicht so einfach Platz einsparen kann oder dass der Platz an unerwarteten Stellen verbraucht wird.

0 Stimmen

Aus meinen Erfahrungen mit "normalen" Profilern weiß ich, dass meine Intuitionen darüber, wohin die Ressourcen gehen, oft falsch sind. Es reicht also nicht aus, nur eine visuelle Inspektion einer .map-Datei vorzunehmen und einfach zu erraten, welche Klassen/Funktionen/Bibliotheken viel Platz benötigen.

0 Stimmen

@Qwertie: Ich weiß, was du meinst, aber wenn eine Ressource aus einem schlechten Grund in großer Menge vorhanden ist, kann eine spärliche Probenahme der Ressource und die Bestimmung des Grundes hinter jeder Probe das Problem aufdecken. Man braucht kein Instrument, das zwar genau misst, aber wenig Aufschluss gibt. Sie brauchen etwas, das grob misst, aber maximalen Einblick gewährt.

2voto

tinman Punkte 5575

Ich konnte nicht bekommen nm zu arbeiten, aber ich habe ein nützliches Tool gefunden, das Sizer . Es liest die Debug-Informationen, die von Visual Studio unter Verwendung der Debug Interface Access-Bibliotheken erstellt wurden. Es ist ziemlich einfach zu bedienen, wie auf der Website beschrieben.

  1. Kompilieren mit Debugging-Informationen in der Programmdatenbankdatei (.pdb)
  2. Sizer über die Befehlszeile ausführen, z. B. Sizer.exe <path-to-exe-file> . Die Ausgabe erfolgt nach stdout, so dass Sie wahrscheinlich in eine Datei umleiten möchten.

Die Codegrößen sind in verschiedene Abschnitte unterteilt und nach Funktion, Daten, Klasse usw. gruppiert, wobei jeder Abschnitt in absteigender Reihenfolge der Codegröße sortiert ist.

1voto

Michael Punkte 52790

Schauen Sie nicht nur auf den Code - Ressourcen können leicht ein Wachstum von mehreren Megabyte verursachen.

0 Stimmen

Glücklicherweise lässt sich die Größe von Bitmaps leicht messen - und ist in meinem Fall kein Problem.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X