ภาษา Rust vs C สำหรับการพัฒนาเฟิร์มแวร์ระบบสมองกลฝังตัว

กระแสความนิยมของภาษา Rust กำลังเพิ่มขึ้นอย่างมาก และเริ่มถูกนำไปใช้ในหลายโปรเจกต์ รวมถึงใน Linux kernel ด้วย แต่ก่อนหน้านี้ยังไม่ชัดเจนว่าว่า Rust เหมาะสมกับการพัฒนาเฟิร์มแวร์สำหรับระบบสมองกลฝังตัว (embedded) หรือไม่ เนื่องจากไมโครคอนโทรลเลอร์มีทรัพยากรฮาร์ดแวร์จำกัด จำเป็นต้องใช้หน่วยความจำและพื้นที่จัดเก็บข้อมูลให้น้อยที่สุด และยังต้องมีประสิทธิภาพสูง เช่น เพื่อช่วยลดการใช้พลังงานในอุปกรณ์ที่ใช้แบตเตอรี่

งานวิจัยจาก Cornell University  เรื่อง “Lessons from an Industrial Microcontroller Use Case with Ariel OS” ได้พยายามตอบคำถามนี้ โดยทำการเปรียบเทียบระหว่างภาษา C และภาษา Rust สำหรับระบบสมองกลฝังตัว ซึ่งผลลัพธ์สรุปว่า Rust เป็นตัวเลือกที่สามารถนำมาใช้งานได้จริง :

เมื่อภาษา Rust ได้รับความนิยมมากขึ้นสำหรับการพัฒนาซอฟต์แวร์ระบบที่ปลอดภัยยิ่งขึ้น ก็จำเป็นต้องมีการ “ตรวจสอบความเป็นจริง” สำหรับกลุ่มฮาร์ดแวร์ไมโครคอนโทรลเลอร์ ว่า ecosystem ของ Rust มีความพร้อมแค่ไหนสำหรับงานลักษณะนี้ และในทางปฏิบัติแล้ว Rust สามารถแข่งขันกับภาษา C ได้หรือไม่

งานวิจัยฉบับนี้นำเสนอกรณีศึกษาในอุตสาหกรรม IoT เพื่อช่วยตอบคำถามดังกล่าว โดยมีการวิเคราะห์ทีมพัฒนาสองทีมที่พัฒนาฟังก์ชันเดียวกันพร้อมกัน (ทีมหนึ่งใช้ภาษา C อีกทีมใช้ Rust) ตลอดระยะเวลาหลายเดือน พร้อมทั้งเปรียบเทียบแนวทาง ผลลัพธ์ และกระบวนการพัฒนาแบบ iterative ของทั้งสองทีม ผลการวิเคราะห์และการวัดผลบนฮาร์ดแวร์จริงแสดงให้เห็นว่า ไม่มีเหตุผลที่ชัดเจนในการเลือกภาษา C เหนือ Rust สำหรับการพัฒนาเฟิร์มแวร์บนไมโครคอนโทรลเลอร์ เมื่อพิจารณาจากขนาดการใช้หน่วยความจำ (memory footprint) หรือความเร็วในการประมวลผล

นอกจากนี้ยังพบว่า Ariel OS สามารถทำหน้าที่เป็น runtime ของระบบที่มีประสิทธิภาพและพกพาได้ โดยมีขนาดเล็กกว่าชุดซอฟต์แวร์แบบ bare-metal ที่พัฒนาในภาษา C ซึ่งถือเป็นแนวทางมาตรฐานในงานลักษณะนี้โดยสรุป งานวิจัยชี้ว่า Rust เป็นตัวเลือกที่เหมาะสม สำหรับการพัฒนาเฟิร์มแวร์ในปัจจุบัน

สามารถเข้าไปอ่านงานวิจัยฉบับเต็ม (PDF) เพื่อทำความเข้าใจวิธีการทดลองและผลลัพธ์ในรายละเอียดมากยิ่งขึ้น

SensorTIle.Box PRO test Rust vs C

ฮาร์ดแวร์ที่ใช้ในการทดลองคือ SensorTile.box Pro devkit เป็นชุดพัฒนาที่มาพร้อมกับไมโครคอนโทรลเลอร์ STMicro STM32U585AI ใช้สถาปัตยกรรม Arm Cortex-M33 และรองรับการเชื่อมต่อ BLE และ NFC (แม้ในการทดลองนี้จะไม่ได้ใช้งาน) อีกทั้งยังมีเซ็นเซอร์ IMU แบบ 6 แกน รุ่น LSM6DSV16X รวมอยู่ด้วย นอกจากนี้ยังมี ST AIoT Craft Edge AI Suite ที่ช่วยให้สามารถประมวลผล AI กับข้อมูลจากเซ็นเซอร์ได้โดยตรงบนอุปกรณ์ (edge AI)

ตัว devkit ทำงานด้วยเฟิร์มแวร์ Vanilla Data Logger (VDL) ซึ่งเขียนด้วยภาษา C หรือ Rust และสื่อสารกับคอมพิวเตอร์ที่รันโปรแกรม GUI ผ่านโปรโตคอล Vanilla Datalog Protocol (VDP) โดยเชื่อมต่อผ่านอินเทอร์เฟซ UART

VDL firmware ST AIoT Craft PC communication

แต่ละทีมทำงานแยกกันเป็นเวลา 6 สัปดาห์ในระยะที่ 1 ของการพัฒนาเฟิร์มแวร์ VDL โดยใช้ภาษา C และ Rust จากนั้นจึงทำงานร่วมกันต่ออีก 4 สัปดาห์เพื่อปรับปรุงและเพิ่มประสิทธิภาพผลงานของกันและกัน การพัฒนาในฝั่งภาษา C ใช้ STM32CubeMX ร่วมกับการออกแบบ Finite State Machine (FSM) ที่เขียนแบบ bare-metal ด้วยภาษา C และใช้ไลบรารีโอเพนซอร์ส Parson library สำหรับการ serialize/deserialize ข้อมูล JSON (หมายเหตุ: มีการใช้การจัดสรรหน่วยความจำแบบไดนามิก)

VDL App C language
การพัฒนาโดยใช้ภาษา C

เฟิร์มแวร์ฝั่งภาษา Rust ใช้ Ariel OS ซึ่งเป็นระบบปฏิบัติการเรียลไทม์ (RTOS) สำหรับไมโครคอนโทรลเลอร์ และมีการจัดการ serialize/deserialize ข้อมูล JSON โดยใช้ serde crate, ซึ่งเป็นเฟรมเวิร์กสำหรับการแปลงข้อมูล และ heapless crate สำหรับการจัดการหน่วยความจำแบบสแตติก (static memory allocation)

VDL App Rust language
การพัฒนาโดยใช้ภาษา Rust

เนื่องจากสถาปัตยกรรมของทั้งสองฝั่งมีความแตกต่างกันพอสมควร การเปรียบเทียบจึงไม่ใช่แบบ C vs Rust โดยตรงทั้งหมด แต่ด้านล่างนี้คือผลลัพธ์สุดท้ายในแง่ของการใช้หน่วยความจำและพื้นที่จัดเก็บข้อมูล

หน่วยวัด (bytes)VDL-CVDL-RustΔ (Rust − C)
.text66,24069,7643,524
ROM รวม76,74484,1007,356
Stack RAM2,04810,2408,192
Static RAM14,96014,400-560
Heap RAM25,6000-25,600
RAM รวม44,65624,640-20,016

ไบนารีของเฟิร์มแวร์ VDL ทั้งสองแบบมีขนาดค่อนข้างเล็ก แต่เฟิร์มแวร์ที่เขียนด้วยภาษา C ก็ยังคงมีขนาดเล็กกว่าฝั่ง Rust เล็กน้อย ซึ่งในกรณีนี้อาจไม่ใช่ประเด็นสำคัญ เนื่องจาก STM32U585AI มีหน่วยความจำแฟลชถึง 2MB แต่ในกรณีของไมโครคอนโทรลเลอร์ที่มีทรัพยากรจำกัดมากกว่านี้ อาจเริ่มมีผลกระทบได้ หากเข้าใกล้ขีดจำกัดของพื้นที่จัดเก็บ ก็อาจจำเป็นต้องปรับแต่ง (optimize) เพิ่มเติม หรือเลือกใช้ชิปตัวอื่นแทน สำหรับการเปรียบเทียบด้าน RAM นั้นมีความซับซ้อนมากกว่า เนื่องจากฝั่ง C มีการใช้การจัดสรรหน่วยความจำแบบไดนามิก (dynamic memory allocation) ซึ่งต้องใช้ Heap RAM โดยตัวเลขที่แสดงเป็นค่าการใช้งาน Heap สูงสุด (peak) ที่วัดได้ นอกจากนี้ งานวิจัยยังระบุว่า “ยังมีตัวเลือกอื่นที่ใช้หน่วยความจำน้อยกว่า และไม่จำเป็นต้องใช้ heap เลย” เมื่อเทียบกับการใช้ไลบรารี Parson เนื่องจากการปรับแต่งหน่วยความจำไม่ใช่เป้าหมายหลักของการทดลองครั้งนี้

C vs Rust firmware breakdown
การวิเคราะห์เฟิร์มแวร์ C vs Rust

เฟิร์มแวร์ทั้งที่พัฒนาด้วยภาษา Rust และ C มีประสิทธิภาพการทำงานอยู่ในระดับเดียวกัน โดยวัดจากค่า Output Data Rate (ODR) ได้ที่ 7,468 Hz กราฟด้านล่างแสดงให้เห็นว่า ไม่ว่าคุณจะเลือกใช้ภาษา C หรือ Rust สำหรับโปรเจกต์ embedded ถัดไป เฟิร์มแวร์ก็จะไม่ได้ถูกปรับให้เหมาะสม ทั้งในด้านขนาดหรือประสิทธิภาพโดยอัตโนมัติ ถ้าไม่ได้ผ่านการปรับแต่งอย่างจริงจัง

C vs Rust performance
ประสิทธิภาพ C vs Rust

ในการทดสอบครั้งแรก การพัฒนาเฟิร์มแวร์ด้วย Rust มีความเร็วมากกว่าฝั่ง C ถึงสองเท่า แต่หลังจากมีการปรับแต่ง (optimization) เพิ่มเติม ทั้ง C และ Rust ก็สลับกันทำผลงานได้ดีที่สุดในแต่ละช่วง โดยการปรับแต่งนั้นรวมถึงการเปลี่ยนแปลงง่าย ๆ เช่น การปิดการทำ logging (สำหรับดีบัก) และการเปิดใช้งาน I-Cache รวมถึงการทำ flash prefetch เพื่อลด latency ของ I2C ทั้งนี้ รายละเอียดเกี่ยวกับข้อควรระวังและปัญหาที่อาจพบ สามารถศึกษาเพิ่มเติมได้จากเอกสาร PDF ฉบับเต็ม

สิ่งที่น่าสนใจคือ ในระยะที่สองของโครงการ แต่ละทีมได้ช่วยกันปรับปรุงเฟิร์มแวร์ของอีกฝ่ายให้ดีขึ้น โดยอาศัยการเปรียบเทียบระหว่างโค้ด C และ Rust ในเชิงทฤษฎี แนวทางที่ดีที่สุดอาจเป็นการใช้ทั้ง C และ Rust ร่วมกันในผลิตภัณฑ์ถัดไป แต่ในทางปฏิบัติแล้วมักทำได้ยาก เนื่องจากข้อจำกัดด้านงบประมาณ ทั้งนี้ ซอร์สโค้ดของโปรเจกต์มีแผนจะเผยแพร่ใน STM32 Hotspot ในอนาคต

แปลจากบทความ : Study compares Rust and C languages for embedded firmware development

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
โฆษณา