คู่มือปรับแต่งประสิทธิภาพ Abseil ของ Jeff Dean
(abseil.io)Abseil Performance Hints (Jeff Dean & Sanjay Ghemawat)
1. ภาพรวม
เอกสารนี้สรุปหลักการทั่วไปและเทคนิคเชิงรูปธรรมเกี่ยวกับการปรับแต่งประสิทธิภาพซอฟต์แวร์ ซึ่ง Google ให้ความสำคัญมาตั้งแต่ช่วงแรก ๆ โดยเน้นการเพิ่มประสิทธิภาพในมุมมองของไบนารีเดี่ยว มากกว่าการจูนระบบแบบกระจายหรือฮาร์ดแวร์ ML
2. ประเด็นสำคัญ
แนวคิดเรื่องประสิทธิภาพ (Thinking about performance)
- ความเข้าใจผิดเกี่ยวกับ "การปรับแต่งก่อนเวลาอันควรคือรากเหง้าของความชั่วร้ายทั้งปวง": คำกล่าวนี้หมายถึงให้มองข้ามประสิทธิภาพเล็กน้อย 97% ไม่ได้แปลว่าต้องพลาดโอกาสสำคัญอีก 3% ที่ส่งผลร้ายแรงด้วย
- ความสำคัญของการปรับปรุงเล็ก ๆ: การเพิ่มความเร็วราว 12% ก็ไม่ใช่เรื่องเล็กน้อยในมุมมองทางวิศวกรรม และเป็นสิ่งจำเป็นสำหรับโปรแกรมคุณภาพสูง
- การเลือกตั้งแต่ต้น: แนวทางแบบ "เขียนให้เรียบง่ายก่อนแล้วค่อยมา optimize ทีหลัง" มักนำไปสู่ประสิทธิภาพโดยรวมที่แย่ลง (Flat Profile) และทำให้ปรับปรุงได้ยาก หากไม่ได้กระทบต่อความอ่านง่ายหรือความซับซ้อนมากนัก ก็ควรเลือกทางเลือกที่เร็วกว่าแต่แรก (เช่น
absl::InlinedVectorแทนstd::vector)
การประมาณ (Estimation)
- สัญชาตญาณและการคำนวณ: ระหว่างเขียนโค้ด ควรประเมินคร่าว ๆ ล่วงหน้าว่าจะส่งผลต่อประสิทธิภาพอย่างไร
- การคำนวณแบบคร่าว ๆ บนกระดาษ (Back-of-the-envelope): ลองคำนวณต้นทุนทรัพยากรโดยประมาณก่อนลงมือทำ (เช่น L1 cache reference 0.5ns, mutex lock 15ns, SSD read 20µs เป็นต้น แล้วใช้ต้นทุนของโอเปอเรชันพื้นฐานเหล่านี้มาประเมินประสิทธิภาพที่คาดได้)
การวัดผล (Measurement)
- การทำโปรไฟล์: การวัดผลอย่างมีประสิทธิภาพคือเครื่องมือที่สำคัญที่สุด ต้องใช้
pprofหรือperfเพื่อตรวจหาคอขวดที่แท้จริง - เคล็ดลับ: ทดสอบด้วย production binary ที่เปิดใช้ optimization flags และเขียน microbenchmark เพื่อตรวจสอบผลกระทบของการเปลี่ยนแปลง
การรับมือกับ Flat Profile
- เมื่อไม่มีคอขวดชัดเจน: หาก CPU profile ออกมาแบนราบ การสะสมการปรับแต่งเล็ก ๆ ระดับ 1% ทั่วทั้งระบบก็เป็นกลยุทธ์ที่ได้ผล
- การปรับปรุงเชิงโครงสร้าง: ควรพิจารณาปรับโครงสร้างลูปในส่วนบนของ call stack ใหม่ หรือเปลี่ยน data structure
ตัวอย่างเทคนิคที่เป็นรูปธรรม
- การปรับปรุงอัลกอริทึม: แทนที่ตรรกะตรวจจับ cycle หรือ deadlock ด้วยอัลกอริทึมที่มีประสิทธิภาพกว่า (เช่น แบบอิง topological sort) เพื่อให้ได้ทั้งความเร็วและความสามารถในการขยายตัว
- การเพิ่มประสิทธิภาพการแทนข้อมูลในหน่วยความจำ: ทำให้ data structure ที่ถูกเข้าถึงบ่อยมีขนาดกะทัดรัดขึ้น (Compact) หรือปรับ memory layout (จัดเรียง field ใหม่ ลด padding) เพื่อเพิ่มประสิทธิภาพของ cache และลดทราฟฟิกบน memory bus
1 ความคิดเห็น
ว้าว..