การตรวจสอบ WebAssembly Binaries
ทุกไฟล์ .wasm คือลำดับของ sections ที่มีหมายเลขกำกับ การทำความเข้าใจว่า section ใด contribute อะไรทำให้สามารถกำหนดเป้าหมายความพยายามในการ optimise ได้อย่างแม่นยำ บทเรียนนี้แสดงเครื่องมือที่นำข้อมูลนั้นขึ้นมา
โครงสร้าง section ของ .wasm
หัวข้อที่มีชื่อว่า “โครงสร้าง section ของ .wasm”WebAssembly binary แบ่งออกเป็น sections มาตรฐานสูงสุดสิบสาม sections แต่ละ section มี ID เฉพาะ แผนภาพด้านล่างแสดง sections ที่พบบ่อยที่สุดและความสัมพันธ์กัน
flowchart TD A[".wasm binary"] --> B["Type section\nfunction signatures"] A --> C["Import section\nJS / host imports"] A --> D["Function section\ntype index per function"] A --> E["Export section\npublic API names"] A --> F["Code section\nactual instructions"] A --> G["Data section\nmemory initialisers"] A --> H["Custom sections\nname debug DWARF producers"]
wasm2wat — human-readable disassembly
หัวข้อที่มีชื่อว่า “wasm2wat — human-readable disassembly”วิธีที่เร็วที่สุดในการอ่าน binary ใดก็ตามคือ wasm2wat ซึ่งสร้าง WAT text representation ขึ้นมาใหม่ รวมถึงชื่อฟังก์ชันหาก name section มีอยู่
# Dump WAT ทั้งหมดไปยัง stdoutwasm2wat add.wasm
# บันทึกลงไฟล์สำหรับแก้ไขหรือ diffwasm2wat add.wasm -o add.wat
# สร้างชื่อ synthetic เมื่อไม่มีชื่อwasm2wat add.wasm --generate-nameswasm-objdump — การตรวจสอบทีละ section
หัวข้อที่มีชื่อว่า “wasm-objdump — การตรวจสอบทีละ section”wasm-objdump -x แสดงสรุปที่มีโครงสร้างของทุก section: type signatures, imports, exports และ function indices เร็วกว่า full disassembly เมื่อคุณต้องการแค่ public API ของ module
# สรุป section ทั้งหมดwasm-objdump -x my.wasm
# Disassemble code section เท่านั้น (แสดงคำสั่งดิบ)wasm-objdump -d my.wasm
# แสดง section เดียวwasm-objdump -j export my.wasmwasm-objdump -j import my.wasmtwiggy — size profiling
หัวข้อที่มีชื่อว่า “twiggy — size profiling”twiggy คือ code-size profiler ที่กำหนดทุก byte ใน binary .wasm ให้กับฟังก์ชันหรือ section เป็นวิธีที่เร็วที่สุดในการตอบคำถาม “ฟังก์ชันใดทำให้ binary ใหญ่?”
# ติดตั้งcargo install twiggy
# แสดง contributors หลักต่อขนาด binarytwiggy top my.wasm
# แสดง retaining paths สำหรับฟังก์ชันเฉพาะtwiggy paths my.wasm --function "some_large_function"
# Output เป็น JSON สำหรับการประมวลผลต่อtwiggy top my.wasm --output-format jsonรายงาน twiggy top มีลักษณะประมาณนี้:
Shallow Bytes | Shallow % | Item----------------+-----------+------------------------------ 14512 | 42.38% | "function names" subsection 8032 | 23.46% | code[42]: some_large_function 3200 | 9.35% | code[17]: decode_utf8Browser DevTools
หัวข้อที่มีชื่อว่า “Browser DevTools”browser สมัยใหม่มาพร้อมกับการสนับสนุน WebAssembly debugging โดยตรงใน DevTools ใน Chrome และ Firefox คุณสามารถเปิด Sources → wasm เพื่อดู disassembly ของทุก module ที่ instantiate แล้ว ตั้ง breakpoints บนคำสั่งแต่ละตัว และตรวจสอบ local variables และ value stack ที่แต่ละ breakpoint
เพื่อให้ได้ชื่อฟังก์ชันที่อ่านได้ใน DevTools คุณต้องการ:
- name section ใน binary (ผลิตโดย
wat2wasm --debug-namesหรือwasm-opt --debuginfo) หรือ - DWARF section ที่ emit โดย Emscripten หรือ clang ด้วย
-g
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
wasm-opt -Oz (การ optimise เชิงรุกสุด) | ได้ size และ speed ที่ดีที่สุดหลัง optimise | build time นานขึ้น และผลลัพธ์ที่เห็นใน wasm2wat/wasm-objdump ห่างไกลจาก source เดิมจนอ่านยากขึ้น |
เก็บ name section (--debug-names) ไว้ | DevTools และ wasm2wat แสดงชื่อฟังก์ชันที่อ่านได้ | เพิ่มขนาด binary ที่ต้อง ship จริง |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ข้าม inspection step แล้วเดาว่าอะไรทำให้ binary ใหญ่ แทนที่จะใช้
twiggy topหาตัวการจริงๆ - เปิด
wasm-optเชิงรุกไปก่อนที่จะรู้จริงๆ ว่า section หรือฟังก์ชันไหนใหญ่หรือช้า - ลบ name section ทิ้งตั้งแต่แรก ทำให้
wasm-objdump,wasm2watและ DevTools อ่าน stack trace ไม่ออกเลย
💡 ตัวอย่างจากของจริง
Emscripten เรียก
wasm-optของ Binaryen อัตโนมัติเมื่อ build ด้วย-O2/-O3ส่วนทีมที่ ship ไปที่ Cloudflare Workers/CDN มักตรวจ binary ด้วยเครื่องมือในบทนี้ก่อนเสมอ เพื่อคุม budget ของขนาด binary ให้อยู่ในเป้าที่ตั้งไว้