- Perbandingan performa Rust dan C adalah persoalan kompleks yang bergantung pada bagaimana premis “semua kondisi sama” didefinisikan
- Dalam kasus inline assembly, kedua bahasa dapat menghasilkan kode assembly yang sama persis, sehingga tidak ada perbedaan kecepatan yang berasal dari bahasanya sendiri
- Pada layout memori struct, Rust dapat memiliki ukuran lebih kecil lewat pengurutan ulang field, tetapi layout yang sama dengan C juga dimungkinkan melalui atribut
#[repr(C)]
- Karena perbedaan pemeriksaan runtime dan perilaku developer, struktur kode dan performa pada proyek nyata bisa berbeda
- Kesimpulannya, tidak ada perbedaan performa yang berasal dari keterbatasan bahasa itu sendiri, dan hasil akhirnya bergantung pada faktor proyek serta developer
Pengajuan masalah dan ambiguitas premis
- Titik awalnya adalah pertanyaan di Reddit: “jika kondisinya sama, bisakah Rust lebih cepat daripada C?”
- Ungkapan “semua kondisi sama” sendiri adalah konsep yang sangat sulit didefinisikan dalam perbandingan bahasa
- Perbandingan performa ditentukan bukan hanya oleh perbedaan bahasa, tetapi juga oleh bentuk kode, keputusan developer, dan optimisasi compiler
Perbandingan inline assembly
- Rust mendukung inline assembly di level bahasa, sedangkan C mengimplementasikannya melalui ekstensi compiler
- Di kedua bahasa, contoh yang sama dapat ditulis dengan menggunakan perintah
rdtsc
- Assembly yang dihasilkan oleh
rustc 1.87.0 dan clang 20.1.0 ditampilkan dalam bentuk yang sepenuhnya identik
- Kasus ini tidak menunjukkan perbedaan performa antarbahasa, tetapi membuktikan bahwa Rust dapat melakukan kontrol level rendah pada tingkat yang sama dengan C
Perbedaan layout struct
- Struct Rust dapat mengoptimalkan penggunaan memori melalui pengurutan ulang field
- Dalam contoh, struct Rust dihitung berukuran 16 byte, sementara struct C yang setara berukuran 24 byte
- Di C, ukuran yang sama hanya bisa diperoleh dengan mengubah urutan field secara manual
- Dengan menggunakan atribut
#[repr(C)] di Rust, kita dapat memaksakan layout memori yang sama dengan C
Faktor sosial dan developer
- Berkat pemeriksaan keamanan Rust, ada kasus di mana developer dapat mencoba optimisasi yang lebih agresif
- Dalam proyek Stylo milik Mozilla, dua upaya paralelisasi dengan C++ gagal, tetapi berhasil diimplementasikan dengan Rust
- Bahkan pada proyek yang sama, performa dan stabilitas kode hasil akhirnya bisa berbeda tergantung bahasa dan tingkat keahlian developer
- Karena hasil dari “pekerjaan yang sama” bisa berbeda antara developer pemula dan ahli, serta menurut tingkat penguasaan bahasa, perbandingan sederhana menjadi sulit
Pemeriksaan compile time dan runtime
- Banyak pemeriksaan keamanan Rust dilakukan pada compile time, tetapi sebagian tetap menjadi pemeriksaan runtime
- Sebagai contoh, saat mengakses
array[0], Rust melakukan bounds check, sedangkan C tidak
- Jika menggunakan
get_unchecked() di Rust, perilakunya bisa dibuat sama seperti C
- Jika compiler dapat membuktikan keamanannya, di kedua bahasa pemeriksaan dapat dihapus lewat optimisasi
- Perbedaan seperti ini memengaruhi cara penulisan kode dan pada akhirnya dapat menimbulkan perbedaan performa
Kesimpulan
- Bahkan jika C diasumsikan sebagai “bahasa tercepat”, tidak ada alasan Rust tidak bisa mencapai tingkat performa yang sama
- Alih-alih keterbatasan bahasa itu sendiri, karakteristik proyek, kemampuan developer, batas waktu, dan variabel eksternal lain yang menentukan perbedaan performa
- Karena itu, pertanyaan “apakah Rust lebih cepat daripada C?” lebih tepat dipahami sebagai masalah konteks rekayasa daripada sekadar perbandingan bahasa
7 komentar
Opini Hacker News
Singkatnya, kecepatan maksimum hampir sama, tetapi pada kode nyata perbedaannya besar
Terutama multithreading adalah variabel yang sangat besar. Di Rust, semua variabel global harus thread-safe baik memakai thread maupun tidak, dan borrow checker membatasi akses memori hanya menjadi berbagi atau memodifikasi
Karena itu, di Rust menulis kode multithread hampir terasa seperti default. Sebaliknya, di C membuat thread sendiri terasa membebani karena masalah kompatibilitas platform atau risiko debugging
Membangun thread di C tidak terlalu sulit, tetapi lebih merepotkan dibanding Rust dengan
std::thread::spawn(move || { ... });Yang lebih berpengaruh daripada keamanan memori adalah model konkurensi bahasanya. Go tetap mudah diparalelkan dengan
go f()meski tidak memory-safeSecara pribadi, saya lebih sering melihat heisenbug di Go
#pragma omp for, di C pun paralelisasi bisa dilakukan dengan mudahBerkat traits di Rust, kita bisa membuat abstraksi yang lebih cepat dan lebih fleksibel
Di C hal ini bisa ditiru dengan macro atau function pointer, tetapi di Rust pemanggil bisa memilih dynamic dispatch atau static dispatch
Di lingkungan embedded, function pointer merusak cache dan menurunkan performa, sedangkan Rust traits bisa dioptimalkan lewat inline sehingga jauh lebih efisien
Baik Rust maupun C pada akhirnya harus ditangani sampai level byte, dan sekarang alat untuk binary patching juga sudah semakin bagus sehingga mudah dimanfaatkan
Box<dyn Trait>pada function signature, pemanggil dipaksa memakai dynamic dispatchKalau memakai
impl Trait, pemanggil masih punya pilihanSecara pribadi, saya melihat Rust, C, dan C++ hampir berada di keluarga bahasa low-level yang sama, jadi perbedaan performanya sangat kecil
Aturan aliasing Rust yang ketat menguntungkan optimasi, dan UB (undefined behavior) di C/C++ memang ada demi performa
Selain itu, generic di Rust dan C++ jauh lebih kuat daripada di C, sehingga misalnya pengurutan berbasis template lebih mudah di-inline dibanding
qsort()Saya rasa perdebatan soal kecepatan antarbahasa seperti ini kebanyakan tidak ada gunanya
Yang menentukan performa lebih besar adalah implementasi compiler daripada bahasa itu sendiri
Rust, C, dan C++ semuanya bahasa tingkat rendah, tetapi definisi “cepat” itu penting
Apakah yang dimaksud adalah kecepatan tertinggi dari kode yang dioptimalkan pakar, atau peluang developer rata-rata menulis kode cepat dalam anggaran yang ada
Namun jika optimasi dilakukan manual, perbedaan antarbahasa hampir hilang
Meski begitu, Rust punya sedikit keunggulan karena lebih mudah dipakai untuk menulis kode cepat
Saya tadinya mengira keunggulan Rust ada pada multithreading dan alokasi di stack
Berkat model ownership, lebih banyak hal bisa diletakkan di stack dibanding C/C++, sehingga overhead malloc/free berkurang
Topik seperti ini sering memicu perdebatan emosional, jadi saya ingin membahas perbedaan cara berpikir daripada angka-angka spesifik
Saat membahas “kecepatan” suatu bahasa, ada dua hal yang perlu dilihat
Rust dan C hampir tidak punya runtime check, sehingga lebih cepat daripada Python atau JS
Namun, Rust menyampaikan informasi aliasing dengan lebih baik sehingga ada lebih banyak peluang optimasi
Dalam mode debug, ia bisa selambat Ruby, tetapi dalam mode rilis kecepatannya setara C
Dibanding C, C++ atau Rust punya fitur compile-time yang lebih kaya sehingga lebih mudah menulis kode cepat
Misalnya, kode ini hampir mustahil dilakukan di C
Di C, dibutuhkan alat eksternal seperti re2c
Assembly bukan bagian dari standar C, jadi sulit dibandingkan langsung dengan Rust, dan Rust justru lebih dekat sifatnya dengan proyek GCC
Apakah suatu bahasa itu “cepat” pada akhirnya bergantung pada implementasi dan konteks
Dibanding kecepatan bahasa itu sendiri, kombinasi compiler dan hardware memberi pengaruh yang lebih besar
Rata-rata, saya tidak tahu bahasa mana yang paling cepat, tetapi sepertinya penyebarannya paling besar ada di C++.
Dalam embedded, pemrograman dilakukan sambil mempertimbangkan sampai ukuran cache line hardware. Ini kemungkinan soal seberapa jauh programmer bisa melakukan optimasi ekstrem di atas bahasa, serta masalah performa standard library dan compiler, tetapi karena pada akhirnya keduanya sama-sama mendukung level rendah, perbedaan overhead kecil sepertinya hanya berada pada tingkat yang sangat minim. Jadi rasanya ini bukan perdebatan yang terlalu bermakna.. Jika butuh optimasi ekstrem, pada akhirnya tetap diperlukan campur tangan manusia. Compiler tidak sesempurna yang kita bayangkan.
Saya rasa Rust akan menjadi pengganti C++ ketimbang C. C pada praktiknya adalah satu-satunya (atau mungkin yang terakhir) bahasa yang memungkinkan kita memperkirakan kode yang akan dihasilkan compiler…
Anda sengaja melakukannya, ya? Hehe
Itu tergantung pada kemampuan kompiler.
Kalau merakit kode yang sama, hasilnya akan terlihat.
Orang-orang ffmpeg sepertinya berpikir bahwa Rust bukan berarti lebih cepat daripada C wkwk https://www.memorysafety.org/blog/rav1d-perf-bounty/