pahole - تحليل تخطيط الهيكل وخط Cache
pahole (“poke-a-hole”) يقرأ معلومات تصحيح DWARF أو BTF ويطبع تخطيط الذاكرة الفعلي لهياكل C — حيث يجلس كل حقل وكم من الحشو أدرجه المترجم وكم عدد خطوط الكاش التي يمتد الهيكل. المترجمات تحشو الهياكل لإرضاء المحاذاة والهيكل المهمل مرتب يمكن أن يضيع عشرات البايتات ويمتد خطوط كاش إضافية. على بيانات ساخنة تُرجم مباشرة إلى cache misses. pahole يجعل الحشو مرئي حتى تتمكن من إعادة ترتيب الحقول وتقليل ذلك.
التثبيت
| المنصة | الأمر |
|---|
| Debian/Ubuntu | sudo apt install dwarves |
| Fedora/RHEL | sudo dnf install dwarves |
| Arch Linux | sudo pacman -S pahole |
| من المصدر | build the dwarves project |
| التحقق | pahole --version |
يجب بناء الثنائي بمعلومات التصحيح (-g). الثنائيات المجردة لا تحتوي على شيء لـ pahole لقراءته.
الاستخدام الأساسي
| الأمر | الوصف |
|---|
pahole ./myprogram | إظهار جميع الهياكل في الثنائي |
pahole -C mystruct ./myprogram | هيكل محدد واحد |
pahole -C task_struct /sys/kernel/btf/vmlinux | هيكل Kernel عبر BTF |
pahole --sizes ./myprogram | قائمة أحجام الهيكل |
pahole -H 1 ./myprogram | فقط الهياكل مع ≥1 hole |
قراءة الإخراج
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 */
};
| التعليق | المعنى |
|---|
/* offset size */ | byte offset وحجم كل حقل |
XXX N bytes hole | حشو أدرجه المترجم |
size: | إجمالي حجم الهيكل |
cachelines: | كم عدد خطوط 64-byte تمتد |
sum holes: | إجمالي البايتات المهدرة |
last cacheline: | البايتات المستخدمة في السطر الأخير |
البحث عن الهدر عبر Codebase
| الأمر | الأوجد |
|---|
pahole -H 1 ./bin | الهياكل مع ثقوب |
pahole --nr_members ./bin | تصنيف حسب عدد الأعضاء |
pahole -c 2 ./bin | الهياكل التي تمتد ≥2 خطوط كاش |
pahole -E ./bin | توسيع الهياكل المتداخلة inline |
pahole -a ./bin | عرض تفاصيل المحاذاة/الحشو |
# أي الهياكل تهدر أكثر الذاكرة على الحشو؟
pahole -H 8 ./myprogram | head -50
إصلاح التخطيط
الإصلاح القياسي هو ترتيب الحقول من أكبر إلى أصغر محاذاة:
/* قبل: 48 بايت و 11 مهدرة */
struct bad { char flag; long counter; char name[16]; int id; void *ptr; };
/* بعد: 40 بايت و 0 مهدرة */
struct good { long counter; void *ptr; char name[16]; int id; char flag; };
| التقنية | التأثير |
|---|
| الترتيب بالمحاذاة التنازلية | يزيل معظم الثقوب |
| مجموعة الحقول الساخنة معاً | تبقيهم في خط كاش واحد |
| تقسيم الحقول الباردة إلى هيكل ثاني | البيانات الساخنة تبقى كثيفة |
__attribute__((packed)) | يزيل الحشو — لكن قد يبطئ الوصول غير المحاذي |
| Bitfields | Pack small flags |
pahole يمكن حتى أن يقترح إعادة ترتيب مع --reorganize:
pahole --reorganize -C mystruct ./myprogram
Kernel Work (BTF)
| الأمر | الغرض |
|---|
pahole -C task_struct /sys/kernel/btf/vmlinux | فحص هيكل kernel حي |
pahole -J vmlinux | توليد BTF من DWARF |
pahole --btf_encode | ترميز BTF لأدوات eBPF |
توليد BTF هو السبب في أن dwarves اعتماد بناء kernel — eBPF’s CO-RE يعتمد عليه.
عندما يهم هذا
| الحالة | التأثير |
|---|
| ملايين المثيلات من هيكل | توفير الذاكرة يتسع خطياً |
| حلقة ساخنة تلمس حقول الهيكل | خطوط cache أقل = cache misses أقل |
| تسلسل الشبكة/القرص | هياكل أصغر وأقل I/O |
| الذاكرة المضمنة/المقيدة | كل البايت يهم |
| هيكل يُستخدم مرتين | لا تزعج |
pahole مقابل الأدوات ذات الصلة
| الأداة | الإجابات |
|---|
| pahole | كيف يتم تخطيط هذا الهيكل وأين الهدر؟ |
| perf | هل أنا بالفعل cache-missing؟ |
| valgrind (cachegrind) | سلوك الكاش المحاكى |
| heaptrack | حيث تذهب ذاكرة heap؟ |
استخدم perf للتأكيد من cache misses هي اختناق ثم pahole لإصلاح التخطيط.
الموارد