- หากคอมไพล์แพ็กเกจซอร์สโค้ดของ
jq ที่ Ubuntu จัดเตรียมไว้ด้วยตนเอง ประสิทธิภาพอาจดีขึ้นได้สูงสุด 90%
- เพิ่มประสิทธิภาพสูงสุดด้วยการปรับปรุงคอมไพเลอร์ แฟล็กการออปติไมซ์ และตัวจัดสรรหน่วยความจำ
การตั้งค่า
jq ถูกใช้เพื่อประมวลผลไฟล์ GeoJSON ในรูปแบบ JSON
- รันคิวรีเพื่อแสดงชื่อเมืองของ parcel ทั้งหมดที่มีค่ามากกว่าค่าที่กำหนดจากแผนที่ parcel ของ Alameda County Assessor ขนาด 500MB
- บนระบบ Ryzen 9 9950X ใช้เวลาประมาณ 5 วินาที กับไฟล์ที่แคชไว้ จึงตัดสินใจลองปรับปรุงให้เร็วขึ้น
ขั้นตอนที่ 1: คอมไพล์แพ็กเกจใหม่
- ดาวน์โหลดซอร์สโค้ด
jq จาก Launchpad แล้วคอมไพล์ใหม่โดยไม่ใส่แฟล็กใด ๆ
- ผลลัพธ์: ประสิทธิภาพดีขึ้น 2~4%
- ผลการเบนช์มาร์ก
- jq ที่คอมไพล์: เฉลี่ย 4.517 วินาที
- แพ็กเกจมาตรฐานของ Ubuntu: เฉลี่ย 4.641 วินาที
- ปรับปรุงประสิทธิภาพ: เร็วขึ้น 1.03 เท่า
ขั้นตอนที่ 2: ใช้ Clang และแฟล็กออปติไมซ์ขั้นสูง
- คอมไพล์ด้วย Clang-18 และใช้ระดับการออปติไมซ์รวมถึง LTO
- แฟล็กหลักที่ใช้:
-O3 → เพิ่มระดับการออปติไมซ์
-flto → ใช้ Link-Time Optimization
-DNDEBUG → ตัดโค้ดดีบักออก
- ผลการเบนช์มาร์ก
- jq ที่คอมไพล์: เฉลี่ย 3.853 วินาที
- แพ็กเกจมาตรฐานของ Ubuntu: เฉลี่ย 4.631 วินาที
- ปรับปรุงประสิทธิภาพ: เร็วขึ้น 1.20 เท่า
ขั้นตอนที่ 3: เพิ่ม TCMalloc
- ใช้ TCMalloc แทน malloc เริ่มต้นของ GNU libc
- เพิ่ม
-L/usr/lib/x86_64-linux-gnu -ltcmalloc_minimal แล้วคอมไพล์
- ผลการเบนช์มาร์ก
- jq ที่คอมไพล์: เฉลี่ย 3.253 วินาที
- แพ็กเกจมาตรฐานของ Ubuntu: เฉลี่ย 4.611 วินาที
- ปรับปรุงประสิทธิภาพ: เร็วขึ้น 1.42 เท่า
ขั้นตอนที่ 4: ใช้ TCMalloc แบบ dynamic preload
- ใช้ TCMalloc กับแพ็กเกจมาตรฐานของ Ubuntu ผ่าน dynamic preload
- ผลการเบนช์มาร์ก
- jq ปกติ: เฉลี่ย 4.601 วินาที
- jq ที่ใช้ TCMalloc: เฉลี่ย 4.082 วินาที
- ปรับปรุงประสิทธิภาพ: เร็วขึ้น 1.13 เท่า
ขั้นตอนที่ 5: ทดสอบ dynamic preload กับตัวจัดสรรอื่น
- ทดสอบ jemalloc และ mimalloc ซึ่งเป็นตัวจัดสรรหน่วยความจำอื่นที่ Ubuntu มีให้
- mimalloc ให้ประสิทธิภาพดีที่สุด
- ผลการเบนช์มาร์ก
- jq ปกติ: เฉลี่ย 4.123 วินาที
- jq ที่ใช้ TCMalloc: เฉลี่ย 4.130 วินาที
- jq ที่ใช้ Jemalloc: เฉลี่ย 3.510 วินาที
- jq ที่ใช้ Mimalloc: เฉลี่ย 3.154 วินาที → ประสิทธิภาพดีขึ้น 1.31 เท่า
ขั้นตอนที่ 6: คอมไพล์ตรงกับ mimalloc
- ลิงก์ mimalloc แบบสแตติกแทนการใช้ dynamic preload
- ดันประสิทธิภาพได้สูงสุด
- ผลการเบนช์มาร์ก
- jq ที่คอมไพล์: เฉลี่ย 2.428 วินาที
- แพ็กเกจมาตรฐานของ Ubuntu: เฉลี่ย 4.606 วินาที
- ปรับปรุงประสิทธิภาพ: เร็วขึ้น 1.90 เท่า
🚀 ผลลัพธ์สุดท้าย
- jq ที่คอมไพล์เองเร็วกว่าแพ็กเกจ Ubuntu 90%
- ประสิทธิภาพในการประมวลผลไฟล์ JSON ขนาด 2.2GB จำนวน 13,000 ไฟล์:
- jq ที่คอมไพล์: 0.755 วินาที
- jq ปกติ: 1.424 วินาที
- ปรับปรุงประสิทธิภาพ: ประมาณ 2 เท่า
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
หัวข้อ "ทำให้แพ็กเกจ Ubuntu เร็วขึ้น 90% ด้วยการบิลด์ใหม่และเปลี่ยนตัวจัดสรรหน่วยความจำ" ดูเหมือนคลิกเบต
วิศวกรรมคือศิลปะแห่งการประนีประนอม
Gentoo Linux เป็นระบบปฏิบัติการที่ออกแบบมาเพื่อให้ปรับแต่งให้เหมาะกับการใช้งานเฉพาะของผู้ใช้ได้
หากติดตั้งแพ็กเกจอย่าง jq ด้วยตนเอง ก็อาจหลุดจากการอัปเดตด้านความปลอดภัย
การใช้ malloc ที่ไม่เป็นทางการอาจทำให้เกิดบั๊กแปลก ๆ ได้
เมื่ออ่านว่าการเปลี่ยนแปลงเล็กน้อยให้ผลด้านความเร็วอย่างมาก ก็อยากบอกเรื่องนี้กับผู้พัฒนา jq
การคอมไพล์แพ็กเกจจากซอร์สหรือดาวน์โหลดไบนารีทางการอาจมีประโยชน์
ฟีเจอร์
cargo installของ Rust มีประโยชน์เพราะช่วยให้ปรับแต่งให้เหมาะกับแพลตฟอร์มเฉพาะได้หลังจากเปลี่ยนตัวจัดสรรหน่วยความจำแล้ว ก็สามารถบิลด์แพ็กเกจ Ubuntu ใหม่ให้เร็วขึ้น 90% ได้