ปูสีส้มแดงต้นฉบับกำลังเรียงเม็ดหินตัวเลขเชิงนามธรรมลงในรางบัฟเฟอร์บนโต๊ะมิ้นต์

Rust 1.98 format_into: แปลงเลขเป็นข้อความโดยไม่ดึง crate เพิ่ม

พี่โชว์Engineering

งานเขียน log, protocol หรือ CSV ที่แปลงจำนวนเต็มหลายล้านครั้งมักไม่ต้องการความสามารถทั้งหมดของ format! ครับ Rust 1.98 เพิ่ม NumBuffer และเมธอด format_into ให้จำนวนเต็มเขียนตัวเลขฐานสิบลงบัฟเฟอร์ขนาดพอดี แล้วคืน &str ที่ยืมอายุจากบัฟเฟอร์นั้น

WHY: ลดงานทั่วไปในเส้นทางที่เฉพาะมาก

ประกาศ Rust 1.98 ระบุว่าเส้นทางใหม่นี้หลบ dynamic dispatch บางส่วนของ write! และมีผลทดสอบใกล้กับ crate เฉพาะทางอย่าง itoa ประโยชน์จึงอยู่ใน hot path ที่รู้ชัดว่าต้องแปลง primitive integer เป็นเลขฐานสิบ ไม่ใช่คำสั่งให้ลบ format! ทั่ว codebase

แนวใช้คือสร้าง NumBuffer::<u64>::new() แล้วเรียก value.format_into(&mut buffer) ข้อความที่ได้ยืมบัฟเฟอร์อยู่ จึงต้องใช้หรือคัดลอกก่อนนำบัฟเฟอร์เดียวกันไปเขียนค่าถัดไป นี่คล้ายเขียนใบเสร็จลงกระดานลบได้: เร็วและใช้ซ้ำได้ แต่ห้ามเก็บกระดาษอ้างอิงแล้วลบกระดานทับ

รอบนี้เครื่อง local มี rustc 1.96.0 ซึ่งยังไม่มี API ดังกล่าว ผมจึงไม่ใส่ code fence ที่อ้างว่ารันแล้ว และยึด signature กับพฤติกรรมจากเอกสาร 1.98 โดยตรง การตรวจแบบนี้ซื่อสัตย์กว่าการติดป้าย executed ให้ตัวอย่างที่ใช้คนละเวอร์ชัน

ใช้เมื่อไร

เหมาะกับ serializer ที่ควบคุมรูปแบบเอง, metrics label ที่เป็นจำนวนเต็ม, encoder ของ protocol และ log formatter ที่ profiler ชี้ว่าการแปลงเลขเป็นคอขวด หากโค้ดต้องใส่ padding, radix อื่น, locale, หลายชนิดใน template เดียว หรืออ่านง่ายสำคัญกว่าระดับ micro-optimization ให้ใช้ formatting API เดิม

ก่อนถอด dependency ควรเทียบ binary size, latency และ allocation บน workload จริง เพราะการลด crate หนึ่งตัวอาจช่วย supply chain แต่การเขียน adapter เองก็เพิ่มภาระดูแล หาก itoa ถูกใช้ผ่าน trait หรือรองรับชนิดที่กว้างกว่า การย้ายอาจไม่ได้ตรงไปตรงมา

Recap

  • format_into เขียนจำนวนเต็มฐานสิบลง NumBuffer ที่ใช้ซ้ำได้
  • &str ที่คืนมายืมบัฟเฟอร์ จึงอย่าเก็บข้ามการเขียนครั้งถัดไป
  • วัด hot path ก่อนแทน format! หรือ crate เดิม
  • ตัวอย่างต้องรันด้วย Rust 1.98 ขึ้นไป; เครื่องตรวจรอบนี้ยังเป็น 1.96