Hal-hal yang berjalan baik
- Rewrite dilakukan dalam langkah-langkah kecil (bertahap, stop-and-go), berjalan dengan baik, dan kode baru menjadi lebih mudah dibaca serta dipahami
- Dengan memiliki pandangan atas seluruh kode, muncul peluang untuk optimasi performa
- Sekitar 1/3 hingga 1/2 kode yang tidak digunakan berhasil dihapus. Bahasa pemrograman modern seperti Rust atau Go lebih baik dalam menemukan dead code dan memberi tahu pengembang
- Tidak perlu khawatir soal akses di luar batas atau overflow/underflow
- Framework pengujian bawaan sangat berguna
- Senang bisa menghapus file CMake
Hal-hal yang tidak berjalan baik
Tetap harus melacak undefined behavior
- Saat melakukan rewrite bertahap dari C/C++ ke Rust, banyak pointer mentah dan blok
unsafe{} yang harus digunakan
- Aturan Rust tetap berlaku bahkan di dalam
unsafe, tetapi karena compiler tidak memeriksanya, undefined behavior mudah terjadi
- Di dalam
unsafe, aturan beberapa pointer baca-saja XOR satu pointer yang dapat diubah mudah dilanggar
- Miri berperan sebagai penyelamat yang menangkap hal ini
Miri tidak selalu bekerja, dan tetap harus memakai Valgrind
- Jika memakai library yang sebagian ditulis dalam C atau assembly, seperti library kriptografi, Miri tidak bekerja
- Ada banyak kode
unsafe yang tidak diperiksa oleh Miri
- Beberapa pengujian harus dijalankan dengan
valgrind
Tetap harus melacak memory leak
- Pola umum pada C API adalah mengalokasikan memori di
MYLIB_init() dan membebaskannya di MYLIB_release(), tetapi mudah lupa memanggil MYLIB_release
- Pengembang Rust ingin membuat objek pembungkus dengan RAII, tetapi dalam pengujian yang menggunakan C API, fitur ini tidak bisa dipakai
- Dalam logika yang kompleks, sulit selalu memanggil fungsi cleanup. Di C hal ini diatasi dengan
goto, tetapi Rust tidak mendukungnya
- Masalah ini diselesaikan dengan crate
defer, tetapi borrow checker tidak menyukainya
Cross-compilation tidak selalu bekerja
- Seperti Miri, jika memakai library yang memiliki bagian yang diimplementasikan dalam C atau assembly,
cargo build --target=... tidak langsung berjalan
Cbindgen tidak selalu bekerja
- Cbindgen banyak digunakan untuk menghasilkan header C dari codebase Rust, tetapi punya keterbatasan atau bug
ABI yang tidak stabil
- Tipe standard library yang berguna seperti
Option tidak memiliki ABI yang stabil, sehingga harus direplikasi manual dengan anotasi repr(C)
Tidak adanya dukungan untuk custom memory allocator
- Banyak library C memungkinkan pengguna menyediakan allocator saat runtime. Di Rust, allocator global hanya bisa dipilih saat compile time
- Masalah pembersihan resource bisa diatasi dengan arena allocator, tetapi ini tidak idiomatis di Rust dan tidak terintegrasi dengan standard library
Kompleksitas
- Kompleksitas meningkat karena perlu memakai hal seperti
UnsafeCell, RefCell, MaybeUninit, dan Pin untuk menangani FFI
- Rust murni saja sudah kompleks, dan ketika lapisan FFI ditambahkan, hasilnya menjadi buas
- Ada juga pengembang yang menolak mengerjakan codebase ini karena kompleksitas Rust
Kesimpulan
- Secara umum puas dengan rewrite ke Rust, tetapi ada kekecewaan di beberapa area, dan usaha yang dibutuhkan jauh lebih besar dari perkiraan
- Rust yang banyak berinteraksi dengan C terasa seperti bahasa yang sepenuhnya berbeda dibanding memakai Rust murni. Gesekannya besar dan jebakannya banyak. Banyak masalah C++ yang diklaim Rust selesaikan ternyata sama sekali belum terselesaikan
- Sangat berterima kasih kepada para pengembang Rust, Miri, cbindgen, dan lainnya. Mereka telah melakukan pekerjaan luar biasa. Meski begitu, bahasa dan tool saat banyak memakai C FFI terasa belum matang dan hampir seperti masih sebelum v1.0
- Jika ergonomi
unsafe, standard library, dokumentasi, tool, dan ABI yang tidak stabil membaik ke depan, pengalamannya bisa menjadi lebih menyenangkan
- Microsoft dan Google tampaknya juga merasakan semua hal ini, sehingga mereka benar-benar berinvestasi dana di area ini
- Jika belum mengenal Rust, sebaiknya proyek pertama memakai Rust murni dan menjauhi topik FFI
- Awalnya sempat mempertimbangkan memakai Zig atau Odin untuk rewrite ini, tetapi tidak ingin menggunakan bahasa pra-v1.0 untuk codebase produksi perusahaan. Kini jadi penasaran apakah pengalamannya benar-benar akan lebih buruk daripada Rust. Mungkin model Rust memang benar-benar tidak cocok dengan model C (atau model C++), sehingga gesekannya terlalu besar saat keduanya dipakai bersama
- Jika harus mengerjakan pekerjaan serupa lagi ke depan, Zig akan sangat dipertimbangkan. Setiap kali seseorang berkata, "tulis ulang saja dengan Rust", tunjukkan tulisan ini dan tanyakan apakah mereka berubah pikiran
12 komentar
Meskipun Zig masih pre-v1, ia bisa memakai banyak library C sehingga ternyata cukup berguna. Untuk menambahkan sesuatu ke proyek berbasis C yang sudah berjalan, Zig bisa jadi lebih baik daripada Rust.
Saat melihat Rust, begitu melihat keyword
unsafe, saya langsung merasakan sensasi waswas...Saya tidak berpikir Rust bisa menyelesaikan masalah-masalah kronis yang dimiliki C++. Ini lebih dari sudut pandang praktis ketimbang sudut pandang sintaksis.
Alasannya:
Sudah terlalu banyak sistem production yang menggunakan C/C++. Dan semuanya berjalan dengan stabil. Selain itu, kebanyakan juga tidak merasa perlu mem-porting ini ke Rust.
Pada dasarnya hardware tidak dirancang dengan asumsi reference counting. Banyak penggunaan C/C++ memang ditujukan untuk mengendalikan hardware, OS, driver, dan lapisan biner dengan cepat, tetapi untuk mendukung Rust, pada akhirnya pengembang low-level harus tetap mengelola sendiri lifecycle resource dengan memanfaatkan
unsafe, dan ini juga merupakan biaya besar.Saya pikir pengalaman penulis jauh lebih penting daripada nilai potensial bahasa dan pembahasan yang bersifat teoretis.
Menurut saya, tingkat pengelolaan resource di bidang-bidang yang benar-benar membutuhkan bahasa setingkat C/C++ itu seperti serba tanggung jika ingin digantikan dengan Rust.
Tulisan ini juga tampaknya salah memahami Rust lalu langsung menerjang.
Kalau melihat isinya, ini tampaknya seperti library yang harus sering berkomunikasi dengan pihak luar Rust, dan pada titik itu memang sudah pasti akan jadi berantakan... Dari awal pun, untuk ukuran bahasa native, memang tidak ada yang benar-benar tidak berantakan; Rust hanya membungkus hal-hal itu dengan aman di tingkat bahasa, jadi semakin banyak titik kontak dengan dunia di luar bahasa, semakin banyak pula keunggulannya yang hilang.
Sampai tingkat tertentu itu benar, tetapi dalam lingkungan pengembangan pada artikel aslinya memang wajar kalau itu tidak terselesaikan. Menurut saya masalahnya adalah mereka mendekati Rust seolah-olah itu obat mujarab untuk segala hal.
Saya merasa maksudnya adalah karena dalam proses mengubah C/C++ ke Rust secara bertahap, mau tidak mau harus menggunakan
unsafe, jadi mengubahnya ke Rust tidak terlalu bermakna. Daripada mengubahnya secara bertahap ke Rust, saya akan memilih Zig. Namun, di bagian mana dalam artikel disebutkan bahwa ini adalah library yang harus sering berkomunikasi dengan pihak luar Rust?Menggunakan FFI berarti berkomunikasi dengan pihak di luar Rust.
Dan kalau melihat isi artikelnya, tampaknya ini bukan sekadar bertukar state atau data sederhana, melainkan interaksi kompleks antara bagian internal dan eksternal.
Bukankah FFI pada akhirnya tidak terhindarkan jika ingin secara bertahap mengganti library yang ditulis dalam C menjadi Rust? Anda kemungkinan harus mengganti bagian-bagian kecil program ke Rust dan menangani sisa bagian C dengan FFI; apakah pekerjaan seperti itu yang Anda maksud sebagai komunikasi dengan pihak luar? Jika demikian, saya rasa wajar jika penulis aslinya menjadi skeptis terhadap Rust. Kecuali seluruh kode diganti sekaligus, manfaat Rust tidak akan terasa, jadi mereka akan merekomendasikan Zig.
^-^
Karena bagian
unsafeditandai secara eksplisit di source code, saya sempat berharap ini akan berguna karena cakupan pengaruh FFI bisa diidentifikasi semua mulai dari entry point program selama tidak memakai blokunsafe, tetapi sepertinya hal itu tidak terlalu terasa bagi penulisnya.Sejak awal memakai FFI, desain yang aman pada dasarnya sudah tidak mungkin lagi.
Betul.
Iya juga, dengan percaya diri menulis bahwa kodenya penuh
unsafe, tapi ternyata masalahnya tetap tidak terselesaikan...