Memilih antara async Rust dan RTOS tradisional untuk pengembangan embedded adalah keputusan arsitektur yang memengaruhi segalanya: latency, ukuran binary, konsumsi RAM, sampai produktivitas developer. Tweede Golf, studio engineering asal Belanda, melakukan perbandingan langsung yang jarang ada: Embassy berbasis async Rust melawan FreeRTOS berbasis C di mikrokontroler STM32F446 yang sama, menjalankan aplikasi yang melakukan aksi identik.
Keduanya dinilai berdasarkan interrupt latency, ukuran program, pemakaian RAM, dan kemudahan programming. Kedua proyek sengaja dibuat normal, bukan di-tuning maksimal, supaya hasilnya mewakili pengalaman developer rata-rata. Pengukuran dilakukan dengan osiloskop Rigol DS1054Z pada STM32F446ZET6 di 180 MHz.
Dua Model Eksekusi yang Berbeda
Async Rust dan RTOS mewakili dua cara berpikir yang berbeda tentang konkurensi. Memahami perbedaannya adalah kunci untuk menilai hasil perbandingan ini.
Fungsi async di Rust adalah gula sintaks untuk fungsi yang mengembalikan future. Future adalah objek state machine yang bisa di-poll. State machine memungkinkan kode melompat ke dalam fungsi dan melanjutkan dari tempat terakhir berhenti, sambil melacak semua variabel yang dipertahankan di titik await. Future Rust bersifat lazy: mereka hanya berjalan saat di-poll. Untuk menjalankan future sampai selesai, polling dipanggil terus sampai berhenti mengembalikan Pending dan mengembalikan Ready(Output). Ini sederhana tapi tidak efisien. Karena itu ada waker: waker bisa memberi sinyal ke executor bahwa sebuah future seharusnya di-poll lagi. Waker bisa dipanggil oleh future itu sendiri atau diberikan ke proses atau thread lain yang menjadi dependensinya.
RTOS membagi semuanya menjadi thread independen. Berbeda dengan task, thread tidak menjalankan state machine, tapi kode normal. Fungsi lama apa pun bisa dijalankan di RTOS. Saat eksekusi thread harus dijeda untuk pindah ke thread lain, seluruh konteks prosesor harus ditangkap dan disimpan karena thread menjalankan kode normal. Saat kode itu dilanjutkan, ia akan membutuhkan konteks prosesor yang sama lagi. Desain multithreading ini cocok untuk thread preemptive: kernel bisa memberi waktu eksekusi yang adil ke semua thread, pengguna bisa menentukan prioritas, dan kernel bisa merespons event dan interupsi dalam waktu yang bisa diprediksi.
Implementasi Embassy
Embassy memakai mekanisme yang sama tapi menambahkan sejumlah batasan. Task harus dialokasikan secara statis karena Embassy tidak ingin bergantung pada allocator. Semua task harus diketahui saat kompilasi. Compiler nightly diperlukan, dan fitur preview type_alias_impl_trait juga diperlukan, karena trait object yang di-box tidak bisa dipakai tanpa allocator.
Untuk banyak periferal, Embassy menyediakan antarmuka async. Contoh task Embassy untuk tombol: task menunggu rising edge, lalu mencatat tombol ditekan, lalu menunggu falling edge. wait_for_rising_edge membuat future baru dan mengembalikannya. Konstruktor future mengonfigurasi interupsi pin. Pada poll pertama, future menaruh waker-nya ke array global waker EXTI. Saat interupsi EXTI terjadi, waker yang sesuai di array itu dipakai untuk membangunkan task yang benar. Saat interupsi keluar, executor meng-poll task lagi, future wait_for_rising_edge menyadari interupsinya sudah terpicu dan mengembalikan bahwa ia siap. Program pun berlanjut.
Satu hal yang tidak dilakukan Embassy adalah preemption. Task aktif hanya berpindah ke task yang lebih penting saat ia await sesuatu. Ini disebut cooperative multitasking. Tapi Embassy punya fitur lain yang membuat ketiadaan fitur ini tidak menjadi masalah, yang dibahas lebih lanjut di artikel.
Program Uji
Aplikasi uji melakukan tiga tugas literal: menyalakan LED setiap 200 ms selama 100 ms sambil memakai fungsi delay executor; mendeteksi tombol user, mengatur interupsi GPIO untuk mendeteksi perubahan sinyal, berbagi boolean atomik tentang status tombol, dan menaruh string ke message queue saat status berubah; dan menulis message queue ke serial, menunggu message queue berisi string lalu mencetaknya.
Yang diukur: berapa lama interupsi GPIO tombol berlangsung, berapa lama thread tombol sampai menunggu lagi, interrupt processing latency antara mulai interupsi GPIO tombol dan thread tombol melanjutkan, ukuran program di section .text, pemakaian memori statis di .data dan .bss, serta kemudahan programming. Semua task dan thread dialokasikan statis.
Prediksi awal penulis: RTOS akan menang di performa karena menaruh flag langsung di thread, kemungkinan lebih cepat daripada menemukan dan memicu waker async. Interrupt latency juga kemungkinan lebih dioptimalkan RTOS karena Embassy tidak bisa meng-preempt task yang berjalan. Untuk ukuran program, program Rust biasanya sedikit lebih besar karena formatting yang lebih mahal dan runtime check yang disisipkan compiler.
Implementasi di Kedua Sisi
Di C, fungsi callback interupsi dibuat manual untuk memberi tahu thread: HAL_GPIO_EXTI_Callback memeriksa pin dan memanggil osThreadFlagsSet dengan handle thread. Di Rust, tidak perlu melakukan apa pun karena Embassy sudah menangani ini.
Untuk menyalakan LED, Rust memakai task async dengan Timer::after dan AtomicBool yang dibaca dengan ordering SeqCst. Periferal diberikan sebagai argumen karena periferal dimodelkan memakai ownership model Rust. Di C, boolean atomik disimpan di global karena task dibuat global dan mengambilnya dari argumen void pointer tidak nyaman.
Untuk message queue, Rust memakai library ArrayVec untuk mendapat tipe ArrayString yang dialokasikan di stack. Di C, dibuat struct sederhana UartMessage dengan array char 32 byte. Kapasitas message queue delapan pesan.
Hasil dan Analisis
Hasil perbandingan menunjukkan nuansa yang menarik. Untuk interrupt latency dan performa, FreeRTOS yang preemptive memang unggul di beberapa pengukuran, seperti yang diprediksi. Tapi selisihnya tidak selalu dramatis, dan dalam banyak kasus penggunaan nyata, performa Embassy sudah memadai.
Untuk ukuran program dan pemakaian RAM statis, Rust dan Embassy menunjukkan keunggulan yang diprediksi: future yang dihasilkan compiler hanya menyimpan variabel yang dipertahankan di titik await dan tidak perlu mengalokasikan ukuran stack penuh untuk setiap task, sehingga pemakaian memori lebih efisien dibandingkan thread RTOS yang butuh stack sendiri.
Untuk kemudahan programming, penulis menilai model async lebih nyaman dipakai. Di dunia web, async/await sudah memenangkan perlombaan melawan thread, dan hal yang sama kemungkinan akan terjadi di embedded. Ownership model Rust juga mencegah seluruh kelas bug yang umum di C, seperti data race dan use-after-free.
Tapi ada trade-off yang jujur: Embassy butuh compiler nightly, semua task harus statis dan dikenal saat kompilasi, dan tidak ada preemption. Untuk sistem dengan persyaratan real-time yang ketat di mana satu task bisa memonopoli CPU, FreeRTOS dengan prioritas thread preemptive masih punya tempat.
Mengapa Perbandingan Ini Langka dan Berharga
Perbandingan langsung antara async Rust dan RTOS di embedded jarang dilakukan dengan disiplin seperti ini. Banyak artikel membandingkan Rust dan C secara umum, atau membahas async Rust secara teoretis tanpa pengukuran. Tweede Golf melakukan sesuatu yang lebih berguna: membangun dua aplikasi nyata yang setara, menjalankannya di hardware yang sama, dan mengukur metrik yang relevan dengan osiloskop.
Pendekatan ini penting karena keputusan memilih framework embedded sering didasarkan pada opini atau tren, bukan data. Tim yang sudah nyaman dengan C dan FreeRTOS mungkin ragu pindah ke Rust karena takut performa atau ukuran binary. Tim yang baru mulai mungkin memilih Rust karena popularitasnya tanpa memahami trade-off real-time. Artikel dengan pengukuran konkret memberi kedua kelompok dasar yang lebih baik untuk mengambil keputusan.
Yang juga berharga adalah kejujurannya tentang bias. Penulis mengaku bias terhadap Rust, tapi tetap berusaha memberi perbandingan yang adil dan mempersilakan pembaca memberi masukan. Sikap ini menyehatkan untuk komunitas teknis yang sering terjebak dalam perang framework yang tidak produktif.
Kapan Memilih FreeRTOS
Meski hasil pengukuran menunjukkan keunggulan Rust di beberapa area, FreeRTOS tetap punya tempat yang jelas di lanskap embedded. Untuk sistem dengan persyaratan real-time yang ketat, di mana keterlambatan respons dalam mikrodetik bisa berarti kegagalan, preemption dan prioritas thread FreeRTOS memberi jaminan yang sulit ditandingi model cooperative.
FreeRTOS juga unggul dalam hal ekosistem dan kematangan. Ia sudah ada selama lebih dari dua dekade, dipakai di miliaran perangkat, dan punya dokumentasi, buku, serta komunitas yang sangat luas. Tim yang merekrut developer embedded hampir pasti menemukan kandidat yang nyaman dengan C dan FreeRTOS, sementara keahlian Rust embedded masih lebih langka. Faktor ini nyata dan memengaruhi biaya serta risiko proyek.
Untuk proyek yang harus mendukung berbagai vendor mikrokontroler dengan toolchain C yang sudah mapan, atau yang butuh sertifikasi dengan preseden C, FreeRTOS sering menjadi pilihan yang lebih aman. Tidak ada yang salah dengan memilih alat yang teruji untuk pekerjaan yang membutuhkan jaminan.
Kapan Memilih Embassy dan Async Rust
Sebaliknya, Embassy dan async Rust bersinar di skenario yang berbeda. Untuk proyek greenfield di mana tim sudah nyaman dengan Rust, produktivitasnya bisa jauh lebih tinggi. Ownership model Rust mencegah seluruh kelas bug memori dan data race di waktu kompilasi, yang berarti lebih sedikit debugging di lapangan dan siklus pengembangan yang lebih pendek.
Efisiensi memori async Rust juga bernilai nyata untuk perangkat dengan RAM terbatas. Karena future hanya menyimpan variabel yang dipertahankan di titik await, beberapa task bisa berbagi ruang tanpa mengalokasikan stack penuh untuk masing-masing, seperti yang harus dilakukan thread RTOS. Untuk MCU dengan puluhan kilobyte RAM, perbedaan ini bisa menentukan fitur mana yang bisa dimasukkan.
Ekosistem Embassy juga tumbuh cepat: dukungan untuk banyak keluarga MCU, driver async untuk periferal umum, dan integrasi dengan tooling Rust modern seperti cargo dan probe-rs. Bagi developer yang sudah investasi di ekosistem Rust, hambatan masuknya rendah dan hasilnya sering memuaskan. Tren async/await yang sudah memenangkan dunia web juga memberi sinyal bahwa model ini akan semakin matang di embedded.
Kesimpulan
Perbandingan Embassy versus FreeRTOS ini tidak menghasilkan pemenang tunggal, dan itu justru kekuatannya. Untuk developer yang baru memulai proyek embedded dan sudah nyaman dengan Rust, Embassy menawarkan produktivitas tinggi, keamanan memori, dan pemakaian RAM yang efisien. Untuk sistem yang butuh jaminan real-time preemptive atau tim yang sudah terikat ekosistem C, FreeRTOS tetap pilihan solid yang teruji.
Untuk developer embedded di Indonesia, artikel ini layak dibaca lengkap karena datanya diukur, bukan sekadar opini. Keputusan akhirnya tergantung pada kebutuhan proyek: persyaratan latency, budget memori, keahlian tim, dan ekosistem yang sudah ada. Yang jelas, async Rust di embedded sudah bukan lagi eksperimen pinggiran. Ia adalah alternatif serius yang pantas dipertimbangkan di setiap proyek baru.
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬