Rustに反対する議論を提起してみましょう

最近、Rustを批判する記事を読みました。それについては正しいことがたくさんありましたが、私はそれが好きではありませんでした。あまりにも多くのことが非常に物議を醸しています。全体として、Rustを批判する記事を読むことはお勧めできません。これは良くありません。なぜなら、欠点を議論することが重要であり、質の低い不適切な批判の名誉毀損は、残念ながら、本当に良い議論を無視するからです。



だから、私は錆に反対して議論しようとします



すべてのプログラミングが体系的であるとは限りません



Rustはシステムプログラミング言語です。実行時のデータ構成とコード実行動作を正確に制御して、パフォーマンスと柔軟性を最大限に高めます。他のシステムプログラミング言語とは異なり、メモリの安全性も提供します。バグのあるプログラムは明確に定義された方法で終了し、(潜在的に危険な)未定義の動作を防ぎます。



ただし、ほとんどの場合、絶対的なパフォーマンスやハードウェアリソースの制御は必要ありません。このような状況では、KotlinやGoなどの最新の管理言語は、動的に管理されるメモリガベージコレクタを使用することで、まともな速度、うらやましいパフォーマンス、メモリの安全性を提供します。



複雑



プログラマーの時間は高くつき、Rustの場合、言語自体を学ぶのに多くの時間を費やす必要があります。コミュニティは質の高い教材を作成するために一生懸命取り組んできましたが、言語は非常に大きいです。Rustでプロジェクトを書き直すことは有益ですが、言語自体を学ぶことは費用がかかりすぎる可能性があります。



改善された制御の代償は、選択の呪いです:



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>    }


Kotlinでは、クラスを作成しFoo(val bar: Bar)て問題の解決を開始します。Rustでは、特別な構文を使用して、場合によっては重要な選択を行う必要があります。



理由のためにこのすべての複雑さ-私たちはより単純でよりメモリセーフな低レベル言語を作成する方法を知りません。ただし、すべてのタスクに低レベルの言語が必要なわけではありません。VazaSank時にC ++が浮き続ける理由



のプレゼンテーションも参照してください



コンパイル時間



コンパイル時間は普遍的な要素です。ある言語のプログラムの実行が遅いが、この言語では高速コンパイルが可能である場合、プログラマーはプログラムの起動を高速化するために最適化するためのより多くの時間を持っています!ジェネリック医薬品のジレンマ、錆が意図的に遅いのコンパイラを選択しました。これはある程度理にかなっていますが(実行時間は本当に高速化されています)、大規模なプロジェクトでは妥当なビルド時間のために懸命に戦う必要があります。おそらくプロダクションコンパイラで最も高度なインクリメンタルコンパイルアルゴリズム実装しますが、言語の組み込みコンパイルモデルと戦うのと少し似ています。







rustc



C ++とは異なり、Rustアセンブリは制限まで並列化されません。並列プロセスの数は、依存関係グラフのクリティカルパスの長さによって制限されます。コンパイルするコアが40を超える場合、違いは顕著になります。



Rustには、pimplイディオムの類似物もありません。そのため、クレートを変更するには、その逆依存関係をすべて再コンパイルする必要があります(単に再リンクするだけではありません)。



成熟



5年は間違いなく短い時間なので、Rustは若い言語です。将来は明るいように見えますが、10年後には、RustではなくCでプログラミングする可能性が高くなります(Lindy効果を参照)。何十年もソフトウェアを作成している場合は、新しいテクノロジーを選択するリスクを真剣に検討する必要があります(ただし、90年代のバンキングソフトウェアにCobolではなくJavaを選択することが、振り返ってみると正しい選択であることが判明しました)。



Rustの完全な実装は、rustcコンパイラだけです。最先端の代替mrustc実装多くの静的セキュリティチェックを意図的にスキップします。現在、rustcは、プロダクション対応のバックエンドであるLLVMのみをサポートしています。その結果、ここでは、プロセッサアーキテクチャのサポートは、GCCが実装されているCよりも狭く、独自のベンダー固有のコンパイラも多数サポートされています。



最後に、Rustには公式の仕様はありません。現在の仕様は不完全であり、いくつかのマイナーな実装の詳細は文書化されていません。



代替案



Rustの他に、C、C ++、Adaなど、システムプログラミング用の他の言語があります。



最新のC ++はセキュリティを向上させるためのツールガイドライン提供しますRustスタイルのオブジェクトの生涯安全提案もあります! Rustとは異なり、これらのツールを使用しても、メモリの安全性の問題がないことは保証されません。ただし、すでに大量のC ++コードをサポートしている場合は、確認することをお勧めします。おそらく、推奨事項に従い、サニタイザー使用すると、セキュリティの問題を解決するのに役立ちます。これは難しいですが、すべてのコードを別の言語で書き直すよりも明らかに簡単です。



Cを使用している場合は、正式な方法を適用して証明できます未定義の動作はありませんまたは、すべてを徹底的にテストします



動的メモリを使用しない限り、Adaはメモリセーフです(決して呼び出さないでくださいfree)。



Rustは興味深いセキュリティコストの言語ですが、それだけではありません。



ツールのセット



Rustのツールは完璧ではありません。基本的なツールキット、コンパイラ、ビルドシステム(カーゴ)は、クラス最高と呼ばれることがよくあります。



ただし、たとえば、一部のランタイム関連ツール(主にヒーププロファイリング用)が欠落しているだけです。ツールが存在しない場合、ランタイムについて考えるのは困難です。さらに、IDEのサポートもJavaの信頼性レベルをはるかに下回っています。Rustでは、数百万行のプログラムの自動化された複雑なリファクタリングは不可能です。



統合



Rustが約束するものは何でも、今日のシステムプログラミングの世界はCとC ++を話します。Rustは意図的にこれらの言語を模倣しようとはしません— C ++またはCABIスタイルのクラスを使用しません。



これは、世界の間に橋を架ける必要があることを意味します。統合はシームレスで安全ではなく、常に費用対効果が高いとは限らず、言語間の同期が必要です。一方で統合が場所で動作し、ツールキットがされて収束し、全体的な複雑さに起因する道に沿って時折障害があります。



1つの特定の問題は、Cargoの自信過剰な世界観(純粋なRustプロジェクトに最適)が、より大きなビルドシステムとの統合を困難にする可能性があることです。



パフォーマンス



「LLVMの使用」は、すべてのパフォーマンスの問題に対する万能のソリューションではありません。一般的にC ++とRustのパフォーマンスを比較するベンチマークについては知りませんが、RustがC ++より劣っているタスクを考えるのは難しいことではありません。



おそらく最大の問題は、Rustの移動セマンティクスが(memcpyマシンコードレベルで)値ベースであることです。一方、C ++セマンティクスは、データを取得できる特別な参照(マシンコードレベルのポインタ)を使用します。理論的には、コンパイラはコピーのチェーンを確認する必要がありますが、実際にはそうではないことがよくあります:#57077。関連する問題は、新しいデータの割り当てがないことです。C++はオブジェクトを所定の位置に作成できますが、Rustはスタックとの間でバイトをコピーする必要がある場合があります。



おかしなことに、デフォルトのRust ABI(効率のために安定性を犠牲にしました)は、Cよりもパフォーマンスが悪い場合があります:#26494



最後に、理論的には、エイリアスに関する情報がはるかに豊富なため、Rustコードの方が効率的ですが、エイリアス関連の最適化を有効にすると、LLVMエラーと誤ったコンパイルが発生します:#54878



しかし、繰り返しになりますが、これらはまれな例であり、比較が反対方向にある場合もあります。例えば、中にBoxいないパフォーマンスの問題、錆に持ってstd::unique_ptr



潜在的に大きな問題は、ジェネリックの定義を持つRustがC ++よりも表現力が低いことです。だからいくつかの公式のトリック 高性能のC ++は、Rustで適切な構文で表現することはできません。



安全でない値



おそらく、このアイデアはunsafe、所有権や借用よりもRustにとってさらに重要です。すべての危険な操作をブロックunsafeと機能に分離し、それらに高レベルの安全なインターフェイスを提供することを主張することにより、次のことを同時に行うシステムを作成することができます。



  1. 信頼できる(チェックされていないunsafeコードは未定義の動作を引き起こすことはできません)、

  2. モジュール式(さまざまな安全でないブロックを個別にテストできます)。


これが事実であることは非常に明白です。ファジーなRustコードはパニックを検出しますが、バッファオーバーフローは検出しません。



しかし、理論的な見通しはそれほど明るくありません。



まず、Rustのメモリモデルの定義がないため、特定の安全でないブロックが有効かどうかを正式に確認することはできません。 「rustcが信頼できること」の非公式な定義があり、ランタイムベリファイア作業が進行中ですが、実際のモデルは明確ではありません。したがって、今日は正常に機能するが、明日は無効であると宣言され、1年以内に新しいコンパイラの最適化に失敗する安全でないコードがどこかにある可能性があります。



第二に、安全でないブロックは実際にはモジュール式ではないと考えられています。十分に強力な安全でないブロックは、実際、言語を拡張する可能性があります。これらの2つの拡張機能は、互いに分離しても問題はありませんが、同時に使用すると未定義の動作になります。「観察可能な同等性と安全でないコード」を参照してください。



最後に、コンパイラには明らかなエラーがあります。



これが私が故意に省略したいくつかのトピックです:



  • 経済学(「Rustプログラマーを見つけるのが難しい」)-「成熟度」セクションは、鶏肉と卵の問題に限定されないこの質問の本質を反映していると思います。

  • 依存関係(「stdlibが小さすぎる/どこでも依存関係が多すぎる」)-Cargoと言語の関連部分がどれほど優れているかを考えると、個人的にはこれを問題とは見なしていません。

  • 動的リンク(「Rustには安定したABIが必要」)-それは強い議論ではないと思います。単形化は基本的に動的リンクと互換性がなく、本当に必要な場合はCABIがあります。ここで改善できると本当に思いますが、Rustの特定の変更について話している可能性は低いです


/ r / rustの ディスカッショントピック



All Articles