コンテンツにスキップ

pahole - 構造体レイアウト & キャッシュラインの分析 チートシート

pahole - 構造体レイアウト & キャッシュラインの分析 チートシート

pahole(「穴をつつく」)はDWARFまたはBTFデバッグ情報を読み込み、C構造体の実際のメモリー レイアウトを出力します—各フィールドの座置、コンパイラーが挿入したパディングの量、構造体がスパンするキャッシュ ラインの数。コンパイラーはアライメントを満たすために構造体をパディング済みにし、不用心に順序付けられた構造体は数十バイトを無駄にし、追加のキャッシュ ラインをまたげます。ホット データ構造でこれは直接キャッシュ ミスに変換されます。paholeは無駄を見えるようにし、フィールドを再順序付けして縮小することができます。

インストール

PlatformCommand
Debian/Ubuntusudo apt install dwarves
Fedora/RHELsudo dnf install dwarves
Arch Linuxsudo pacman -S pahole
From sourcedwarvesプロジェクトをビルド
Verifypahole --version

バイナリーはデバッグ情報でビルドする必要があります(-g)。剥き出しのバイナリーはpaholeが読み取るものはありません。

基本的な使用法

CommandDescription
pahole ./myprogramバイナリー内のすべての構造体を表示
pahole -C mystruct ./myprogram1つの特定の構造体
pahole -C task_struct /sys/kernel/btf/vmlinuxBTF経由のカーネル構造体
pahole --sizes ./myprogram構造体サイズをリスト
pahole -H 1 ./myprogram≥1ホール持つ構造体のみ

出力の読み取り

struct example {
        char                       flag;                 /*     0     1 */

        /* XXX 7 bytes hole, try to pack */

        long int                   counter;              /*     8     8 */
        char                       name[16];             /*    16    16 */
        int                        id;                   /*    32     4 */

        /* XXX 4 bytes hole, try to pack */

        void *                     ptr;                  /*    40     8 */

        /* size: 48, cachelines: 1, members: 5 */
        /* sum members: 37, holes: 2, sum holes: 11 */
};
AnnotationMeaning
/* offset size */各フィールドのバイト オフセットとサイズ
XXX N bytes holeコンパイラーが挿入したパディング
size:合計構造体サイズ
cachelines:スパンするキャッシュ ラインの数
sum holes:総浪費バイト
last cacheline:最後のラインで使用されたバイト

コードベース全体の無駄を検索

CommandFinds
pahole -H 1 ./binホール付き構造体
pahole --nr_members ./binメンバー数でソート済み
pahole -c 2 ./bin≥2キャッシュ ラインをスパンする構造体
pahole -E ./binネストされた構造体をインライン展開
pahole -a ./binアライメント/パッキング詳細を表示
# どの構造体はパディングに最も多くメモリーを浪費するか?
pahole -H 8 ./myprogram | head -50

レイアウトの修正

標準フィックスはフィールドを最大から最小のアライメント順に順序付けするです:

/* Before: 48 bytes, 11 wasted */
struct bad  { char flag; long counter; char name[16]; int id; void *ptr; };

/* After: 40 bytes, 0 wasted */
struct good { long counter; void *ptr; char name[16]; int id; char flag; };
TechniqueEffect
Order by descending alignmentほとんどのホール除去
Group hot fields togetherホット データは1つのキャッシュ ラインに保つ
Split cold fields into a second structホット データは密に保つ
__attribute__((packed))パディング削除—ただしアラインされていないアクセスが遅い可能性があります
Bitfields小さいフラグをパック

paholeは--reorganizeで再順序付けを提案さえできます:

pahole --reorganize -C mystruct ./myprogram

カーネル作業(BTF)

CommandPurpose
pahole -C task_struct /sys/kernel/btf/vmlinuxライブ カーネル構造体を検査
pahole -J vmlinuxDWARFからBTFを生成
pahole --btf_encodeeBPFツーリング用BTFエンコーディング

BTF生成はdwarvesがカーネル ビルド依存関係である理由です—eBPFのCO-REはそれに依存します。

これが重要な場合

SituationImpact
Millions of instances of a structメモリー節約リニア スケール
Hot loop touching struct fieldsキャッシュ ラインが少ない = ミス少ない
Network/disk serialization小さい構造体、I/O少ない
Embedded/constrained memoryすべてのバイト数える
A struct used twice気に留めないでください

pahole対関連ツール

ToolAnswers
paholeこの構造体はどのようにレイアウトされており、無駄はどこ?
perf実際にキャッシュ ミスしている?
valgrind (cachegrind)シミュレートされたキャッシュ動作
heaptrackヒープ メモリーはどこに移動?

perfを使用してキャッシュ ミスがボトルネックであることを確認し、それからpaholeを使用してレイアウトを修正します。

リソース