Mari kita coba mengemukakan argumen yang menentang Rust

Saya baru-baru ini membaca artikel yang mengkritik Rust. Meskipun ada banyak hal yang benar tentangnya, saya tidak menyukainya - terlalu banyak hal yang sangat kontroversial. Secara keseluruhan, saya tidak bisa merekomendasikan membaca artikel apa pun yang mengkritik Rust sama sekali. Ini tidak baik, karena penting untuk membahas kekurangan, dan fitnah terhadap kritik yang berkualitas rendah dan tidak layak, sayangnya, membuat argumen yang sangat bagus diabaikan.



Jadi, saya akan mencoba untuk berdebat melawan Rust.



Tidak semua pemrograman sistematis



Rust adalah bahasa pemrograman sistem. Ini memberikan kontrol yang tepat atas komposisi data dan perilaku eksekusi kode pada waktu proses untuk kinerja dan fleksibilitas maksimum. Tidak seperti bahasa pemrograman sistem lain, ia juga menyediakan keamanan memori - program buggy diakhiri dengan cara yang terdefinisi dengan baik, mencegah perilaku tidak terdefinisi (berpotensi berbahaya).



Namun, dalam kebanyakan kasus, kinerja atau kontrol mutlak atas sumber daya perangkat keras tidak diperlukan. Untuk situasi ini, bahasa terkelola modern seperti Kotlin atau Go memberikan kecepatan yang layak, performa yang membuat iri, dan keamanan memori melalui penggunaan pengumpul sampah memori yang dikelola secara dinamis.



Kompleksitas



Waktu programmer itu mahal, dan dalam kasus Rust, Anda harus menghabiskan banyak waktu untuk mempelajari bahasa itu sendiri. Komunitas telah bekerja keras untuk menciptakan bahan ajar yang berkualitas, tetapi bahasanya sangat luas. Meskipun menguntungkan bagi Anda untuk menulis ulang proyek di Rust, mempelajari bahasanya sendiri bisa jadi terlalu mahal.



Harga untuk kontrol yang lebih baik adalah kutukan pilihan:



struct Foo     { bar: Bar         }
struct Foo<'a> { bar: &'a Bar     }
struct Foo<'a> { bar: &'a mut Bar }
struct Foo     { bar: Box<Bar>    }
struct Foo     { bar: Rc<Bar>     }
struct Foo     { bar: Arc<Bar>    }


Di Kotlin, Anda menulis kelas Foo(val bar: Bar)dan mulai memecahkan masalah. Di Rust, Anda harus membuat pilihan, terkadang yang penting, dengan sintaks khusus.



Semua kerumitan ini karena suatu alasan - kami tidak tahu cara membuat bahasa tingkat rendah yang lebih sederhana dan lebih aman untuk memori. Tetapi tidak setiap tugas membutuhkan bahasa tingkat rendah.



Lihat juga presentasi "Mengapa C ++ Terus Mengambang Saat Vaza Tenggelam" .



Kompilasi waktu



Waktu kompilasi adalah faktor universal. Jika program dalam beberapa bahasa berjalan lambat, tetapi bahasa ini memungkinkan kompilasi cepat, maka programmer akan memiliki lebih banyak waktu untuk mengoptimalkan untuk mempercepat peluncuran program!



Dalam dilema generik, Rust sengaja memilih kompiler lambat. Ini masuk akal (waktu proses benar-benar dipercepat), tetapi Anda harus berjuang keras untuk waktu build yang wajar pada proyek yang lebih besar.



rustcmungkin mengimplementasikan algoritme kompilasi inkremental paling canggih dalam kompiler produksi, tetapi ini seperti melawan model kompilasi bawaan bahasa tersebut.



Tidak seperti C ++, perakitan Rust tidak diparalelkan ke batas, jumlah proses paralel dibatasi oleh panjang jalur kritis dalam grafik ketergantungan. Perbedaannya akan terlihat jika Anda memiliki lebih dari 40 core untuk dikompilasi.



Di Rust, juga tidak ada analog untuk idiom pimpl , jadi mengubah peti membutuhkan kompilasi ulang (dan tidak hanya menautkan ulang) semua dependensi kebalikannya.



Kematangan



Lima tahun pasti waktu yang singkat, jadi Rust adalah bahasa yang masih muda. Meskipun masa depan terlihat cerah, kemungkinan besar dalam waktu sepuluh tahun kami akan membuat program dalam C daripada Rust (lihat efek Lindy ). Jika Anda telah menulis perangkat lunak selama beberapa dekade, Anda harus mempertimbangkan dengan serius risiko memilih teknologi baru (meskipun memilih Java daripada Cobol untuk perangkat lunak perbankan di tahun 90-an ternyata menjadi pilihan yang tepat dalam retrospeksi).



Hanya ada satu implementasi lengkap dari Rust, yaitu penyusun Rustc . Implementasi mrustc alternatif paling canggihsengaja melewati banyak pemeriksaan keamanan statis. Saat ini rustc hanya mendukung satu backend siap produksi, LLVM. Akibatnya, dukungan untuk arsitektur prosesor di sini lebih sempit daripada C, yang memiliki implementasi GCC, serta dukungan untuk sejumlah kompiler khusus vendor.



Terakhir, Rust belum memiliki spesifikasi resmi. Spesifikasi saat ini tidak lengkap dan tidak mendokumentasikan beberapa detail implementasi kecil.



Alternatif



Selain Rust, ada bahasa lain untuk pemrograman sistem, termasuk C, C ++, dan Ada.



C ++ modern menyediakan alat dan pedoman untuk meningkatkan keamanan. Bahkan ada proposal keselamatan seumur hidup objek bergaya Rust! Tidak seperti Rust, menggunakan alat ini tidak menjamin bahwa tidak ada masalah keamanan memori. Tetapi jika Anda sudah mendukung sejumlah besar kode C ++, masuk akal untuk memeriksanya, mungkin mengikuti rekomendasi dan menggunakan pembersih akan membantu dalam memecahkan masalah keamanan. Ini sulit, tetapi jelas lebih mudah daripada menulis ulang semua kode dalam bahasa lain!



Jika Anda menggunakan C, Anda dapat menerapkan metode formal untuk membuktikantidak ada perilaku yang tidak terdefinisi, atau hanya menguji semuanya secara menyeluruh .



Ada adalah memori yang aman kecuali menggunakan memori dinamis (jangan pernah menelepon free).



Rust adalah bahasa biaya-untuk-keamanan yang menarik, tetapi jauh dari satu-satunya!



Set alat



Alat Rust tidak sempurna. Perangkat dasar, penyusun dan sistem pembangunan ( kargo ) sering disebut sebagai yang terbaik di kelasnya.



Namun, misalnya, beberapa alat yang berhubungan dengan runtime (terutama untuk pembuatan profil heap) hilang begitu saja - sulit untuk memikirkan runtime jika alat tersebut tidak ada! Selain itu, dukungan IDE juga jauh dari tingkat keandalan Java. Pemfaktoran ulang kompleks otomatis dari program dengan jutaan baris tidak mungkin dilakukan di Rust.



Integrasi



Apapun yang dijanjikan Rust, dunia pemrograman sistem saat ini berbicara C dan C ++. Rust tidak secara sengaja mencoba meniru bahasa-bahasa ini - Rust tidak menggunakan kelas gaya C ++ atau C ABI.



Ini berarti jembatan perlu dibangun di antara dunia. Integrasi tidak akan mulus, tidak aman, tidak selalu hemat biaya, dan membutuhkan sinkronisasi antar bahasa. Meskipun integrasi berfungsi di beberapa tempat dan perkakasnya menyatu, terkadang ada kendala di sepanjang jalan karena keseluruhan kompleksitas.



Satu masalah khusus adalah bahwa pandangan dunia Cargo yang terlalu percaya diri (bagus untuk proyek Rust murni) dapat mempersulit integrasi dengan sistem build yang lebih besar.



Performa



"Menggunakan LLVM" bukanlah solusi satu ukuran untuk semua untuk semua masalah kinerja. Meskipun saya tidak tahu tentang tolok ukur yang membandingkan kinerja C ++ dan Rust secara umum, tidak sulit untuk memikirkan tugas-tugas yang Rust lebih rendah dari C ++.



Mungkin masalah terbesarnya adalah semantik perpindahan Rust berbasis nilai ( memcpypada level kode mesin). Di sisi lain, semantik C ++ menggunakan referensi khusus tempat data dapat diambil (penunjuk di level kode mesin). Secara teori, kompilator harus melihat rangkaian salinan, dalam praktiknya seringkali tidak demikian: # 57077 . Masalah terkait adalah kurangnya alokasi data baru - Rust terkadang perlu menyalin byte ke / dari tumpukan, sementara C ++ dapat membuat objek di tempat.



Lucunya, Rust ABI default (yang mengorbankan stabilitas demi efisiensi) terkadang berkinerja lebih buruk daripada C: # 26494 .



Terakhir, sementara dalam teori kode Rust harus lebih efisien karena informasi yang lebih kaya secara signifikan tentang alias, mengaktifkan pengoptimalan terkait alias menyebabkan kesalahan LLVM dan kompilasi yang salah: # 54878 .



Tapi, sekali lagi, ini adalah contoh langka, terkadang perbandingannya ke arah lain. Misalnya, di BoxRust tidak ada masalah kinerja, yang ada di std::unique_ptr.



Masalah yang berpotensi lebih besar adalah Rust, dengan definisi generiknya, kurang ekspresif dibandingkan C ++. Jadi beberapa trik formula C ++ untuk performa tinggi tidak dapat diekspresikan dalam Rust dengan sintaks yang baik.



Nilai tidak aman



Mungkin idenya unsafebahkan lebih penting bagi Rust daripada kepemilikan dan pinjaman. Dengan memisahkan semua operasi berbahaya menjadi blok unsafedan fungsi dan bersikeras menyediakannya dengan antarmuka aman tingkat tinggi, dimungkinkan untuk membuat sistem yang secara bersamaan:



  1. dapat diandalkan ( unsafekode yang tidak dicentang tidak dapat menyebabkan perilaku yang tidak ditentukan),

  2. modular (blok tidak aman yang berbeda dapat diuji secara terpisah).


Sangat jelas bahwa ini masalahnya: kode Rust yang kabur menimbulkan kepanikan, tetapi tidak buffer overflows.



Tetapi prospek teoretisnya tidak begitu cerah.



Pertama , tidak ada definisi model memori Rust, jadi tidak mungkin untuk memeriksa secara formal apakah blok tidak aman yang diberikan valid atau tidak. Ada definisi tidak resmi tentang "hal-hal yang dapat dilakukan atau diandalkan oleh Rustc" dan pekerjaan sedang berlangsung pada pemverifikasi waktu proses , tetapi model sebenarnya tidak jelas. Jadi, di suatu tempat mungkin ada beberapa kode tidak aman yang berfungsi dengan baik hari ini, tetapi akan dinyatakan tidak valid besok dan berhenti dalam pengoptimalan compiler baru dalam satu tahun.



Kedua, diyakini bahwa blok yang tidak aman sebenarnya tidak modular. Pemblokiran tidak aman yang cukup kuat sebenarnya dapat memperluas bahasa. Kedua ekstensi ini tidak melakukan kesalahan dalam isolasi satu sama lain, tetapi mengarah pada perilaku yang tidak ditentukan saat digunakan pada saat yang sama: lihat Kesetaraan yang Dapat Diamati dan Kode Tidak Aman.



Akhirnya, ada kesalahan yang jelas dalam kompilator .



Berikut beberapa topik yang sengaja saya hilangkan:



  • Ekonomi ("lebih sulit untuk menemukan programmer Rust") - Saya pikir bagian "Kematangan" menangkap esensi dari pertanyaan ini, yang tidak terbatas pada masalah ayam dan telur.

  • Dependensi ("stdlib terlalu kecil / terlalu banyak dependensi di mana-mana") - mengingat seberapa baik Cargo dan bagian bahasa yang terkait, saya pribadi tidak melihat ini sebagai masalah.

  • Tautan dinamis ("Rust harus memiliki ABI yang stabil") - Saya rasa itu bukan argumen yang kuat. Monomorphization pada dasarnya tidak kompatibel dengan tautan dinamis, dan jika Anda benar-benar perlu, maka ada C ABI. Saya benar-benar berpikir bahwa hal-hal dapat ditingkatkan di sini, tetapi tidak mungkin kita berbicara tentang perubahan spesifik di Rust .


Diskusi tentang / r / rust .



All Articles