「関数サイズ プロファイラー」は存在しますか?
質問
C++ プロジェクトに 3 年間取り組んだ結果、実行可能ファイルは 4 MB に成長しました。この空間がどこへ向かうのか見てみたいと思います。最大のスペース消費者が何であるかを報告できるツールはありますか?クラス別 (クラス内のすべての関数)、テンプレート別 (すべてのインスタンス化)、ライブラリ別 (C 標準ライブラリと STL にどれだけ含まれているか) ごとにサイズが表示されると便利です。exe 内のライブラリごとにいくらですか?)
編集:Windows 上で Visual C++ を使用していることに注意してください。
解決
Linuxの場合, 、使用できます nm
実行可能ファイル内のすべてのシンボルを表示し、サイズ順に逆順に並べ替えます。
$ nm -CSr --size-sort <exe>
オプション:
-C
C++ 名のマングルを解除します。-S
シンボルのサイズを示します。--size-sort
シンボルをサイズで並べ替えます。-r
並べ替えを逆にします。
名前空間ごとまたはクラスごとに結果を取得したい場合は、次のようにすることができます。 grep
' の出力namespace::
', 'namespace::class_name::
', 等.
定義されているシンボルのみを表示したい場合 で 実行可能ファイル(ライブラリなど、他の場所で定義されているものではない)を追加します --defined-only
. 。ただし、未定義のシンボルにはサイズがないため、サイズで並べ替えることでこれに対処する必要があります。
Windowsの場合, 、まだ使用できるはずです nm
バイナリファイル上では、 nm
サポートします コフ バイナリ。インストールできます nm
cygwin経由、またはWindowsの実行可能ファイルをLinuxボックスにコピーして実行することもできます nm
そこにあります。
試してみることもできます dumpbin
, 、Windows 上のバイナリに関する情報をダンプします。シンボルに関する情報を取得するには、 /SYMBOLS
スイッチですが、サイズに関する情報を直接提供しているようには見えません。
他のヒント
Windows の Visual Studio コンパイルでは、この情報は .map ファイル内にあります (.pdb の近くにあります)。
追加した:.map ファイル内の装飾名を人間が判読できる名前に変換するには、 unname.exe Visual Studio に含まれるユーティリティ。コマンドラインで個々の名前を受け入れるか、.map ファイルを渡すこともできます。
例えば、
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 &)"
入手できませんでした nm
私のために働く必要がありましたが、という便利なツールを見つけることができました サイザー. 。Debug Interface Access ライブラリを使用して、Visual Studio によって作成されたデバッグ情報を読み取ります。サイトで説明されているように、使い方は非常に簡単です。
- プログラム データベース (.pdb) ファイル内のデバッグ情報を使用してコンパイルします。
- コマンドラインから sizer を実行します。
Sizer.exe <path-to-exe-file>
. 。出力は標準出力に出力されるため、ファイルにリダイレクトすることをお勧めします。
コード サイズはさまざまなセクションに分類され、関数、データ、クラスなどによってグループ化され、各セクションはコード サイズの降順に並べ替えられます。
コードだけを見てはいけない - 。リソースは、簡単に数メガバイトの成長を引き起こす可能性があります。
リンク マップを取得するか、 dumpbin
シンボルとサイズのリストを取得します。
厳密には必要のないものが大量に取り込まれている可能性があります。
追加した:満足のいく答えが得られましたか?このような問題に対処する方法は 2 つあることに気づきました。
- 何かをする前に測定を行ってください。
- 必要のない大きなものを見つけて破り、それを不可能になるまで繰り返します。
個人的には後者の方が好きです。結果が早く得られます。
アプリは4MBだそうです。実際に必要なサイズが 1MB (またはそのようなサイズ) であると仮定します。つまり、マップ ファイルからルーチンをランダムに選択した場合、それは必要のないものである可能性が 75% あります。それが含まれる原因を調べて、それが本当に必要かどうかを確認してください。
あなたが示した例では、デバイスに依存しないビットマップをラップするクラスが見られました。アプリ内でそのクラスのインスタンスを見つけて、それらを基本的な WIN32 ビットマップに置き換えることもできます。見た目はあまり良くありませんが、アプリのサイズを大幅に節約できます。
それからそれを続けてください。大きな部分を削除するたびに、残りの部分がアプリに占める割合が大きくなります。これは、アプリは縮小しましたが、部分は縮小していないためです。これにより、マップ ファイル内でそれらを見つけやすくなります。