หลักการทำให้แอป Tokio (Rust) เร็วจริง: วัดก่อน แล้วค่อยจูน
Principles for Fast Tokio Applications
บทความที่เผยแพร่เมื่อวันที่ 13 กันยายน 2026 รวบรวมหลักการปฏิบัติสำหรับการทำให้แอปพลิเคชันที่รันบน Tokio ซึ่งเป็น async runtime หลักของ Rust ทำงานได้เร็วจริง โดยเน้นว่าต้องเริ่มจากการวัดก่อนเสมอ ไม่ใช่ไล่แก้ปัญหาตามทฤษฎี เครื่องมือที่ผู้เขียนแนะนำคือ schedule latency histogram ซึ่งเผยอาการที่พบบ่อยที่สุด คือช่วงเวลาหน่วงระหว่างที่งานพร้อมทำงานกับตอนที่มันได้ทำงานจริง
หลักการที่สองคือการสมดุลระหว่างความเป็นธรรมกับการรวมงานเป็นก้อน ถ้าต้องการ latency ต่ำ ควร yield บ่อยเพื่อไม่ให้การเชื่อมต่อเดียวผูกขาดทรัพยากร ตัวอย่างที่ยกมาเป็นเคส Redis ซึ่งการ yield หลังจากอ่านข้อมูลที่พร้อมติดต่อกัน 4 ครั้ง ลด P50 latency จาก 0.967 ms เหลือ 0.105 ms และ P99 จาก 2.548 ms เหลือ 0.320 ms ในทางกลับกัน ถ้าต้องการ throughput ควรรวมงานเป็นก้อนเพื่อเฉลี่ยค่าโสหุ้ย เพราะการ spawn งานเล็ก ๆ ที่ใช้เวลาไม่ถึง 10 ไมโครวินาทีสร้างภาระให้ scheduler โดยไม่จำเป็น
หลักการที่เหลือเกี่ยวกับทรัพยากรที่ใช้ร่วมกัน blocking pool จะกลายเป็นคอขวดที่ราว 50,000 blocking task ต่อวินาทีบนเครื่อง 32 คอร์ และคิวงานส่วนกลางควรอยู่ในสภาพเกือบว่างเสมอถ้าแอปสุขภาพดี ส่วน mutex แบบ blocking สามารถหยุด worker ทั้งรันไทม์พร้อมกันได้ จึงต้องทำ critical section ให้สั้นที่สุดและห้ามถือล็อกขณะทำ I/O หรือรอ future
อีกสองข้อคือการจำกัดการทำงานขนานด้วย semaphore เพื่อกันการ spawn งานแบบไม่มีขอบเขต (ตัวอย่างคือการเชื่อมต่อพร้อมกัน 3,000 รายการ) และการแยก worker ของ Tokio ไปปักหมุดบนคอร์ที่กันไว้เฉพาะ เพราะเมื่อระบบปฏิบัติการมีภาระสูง ความหน่วงจากการจัดตารางของเคอร์เนลอาจสูงถึง 10-20 มิลลิวินาที ซึ่งทำลายงานที่ต้องการความแม่นยำระดับไมโครวินาทีโดยสิ้นเชิง
สำหรับเคสขั้นสูง ผู้เขียนแนะนำการใช้หลายรันไทม์เพื่อแยกลำดับความสำคัญระหว่างงานที่ไวต่อ latency กับงานเบื้องหลัง และการจงใจให้ CPU spin ราว 50 ไมโครวินาทีเพื่อรักษาการควบคุมในแอปที่ต้องการความแม่นยำระดับไมโครวินาที โดยแลกกับการใช้คอร์ที่ไม่คุ้มค่า
แหล่งอ้างอิง
อ่านต้นฉบับที่ dial9-rs bloghttps://dial9-rs.github.io/blog/principles-for-fast-tokio-applications/