プログラミング
Rust Glancer
Rust Glancer (matklad.github.io)
要約
Rust Glancerは、従来のLSPサーバー(例:rust-analyzer)と比較してメモリ使用量を大幅に削減する、新しいRust用LSPサーバーである。この記事は、rust-analyzerのメモリ使用量の多さの原因を、依存クレートの全コード解析やプロシージャマクロの処理などにあると分析し、Rust Glancerのようなアプローチ、すなわち、開いているファイルやメタデータ(.rmetaファイル)のみを解析し、必要に応じて詳細な解析に切り替えることで、パフォーマンスを向上させる可能性を示唆している。
全文翻訳
Rust Glancerは、メモリ使用量を従来の2桁以上削減するRust用の関数型LSPサーバーであり、信じられないほどクールです。
ぜひチェックしてみてください!
この記事はlobste.rsへのコメントとして始まりましたが、もう少し目立つ形で公開した方が良いと判断しました。
ただし、洗練された文章は期待しないでください!
いくつかの考え:
rust-analyzerは行列表現にrowanを使用しています。
はい、rowanはゴミです :P
私は増分解析、増分DOM操作スタイルのリファクタリングについて本当に考えていました。
そしてRowanはそれにかなり適しています。
しかし、それは1%のユースケースです。
99%のユースケースは、あなたが決して見ない6666の依存関係にあるすべてのコードであり、少なくとも浅く分析される必要があります。
リファクタリングを主な目的とする増分ツールであっても、主要なAST構造は配列のリストであるべきです。
それについての実際の記事がそのうち公開されるかもしれません。
ティーザーとして https://youtu.be/G93oYL1ry70 を参照してください。
Rustワークスペースは本当に多くの情報をインデックス化する必要があります。
数千の関数、構造体、トレイト、それらの間の関係、関数本体とそれらの中のステートメントなど。
これらすべてを分析して記憶する必要があり、
「この構造体への参照をすべて見つける」のようなことをしたい場合、本当にごまかすことはできません。
私の理解が正しければ、Rust Glancerは各関数本体を処理したいと考えています。
私はその部分が、ほとんどオーバーヘッドなしで遅延実行(ただし増分ではない!)できるのではないかと思います。
すべてのアイテムをインデックス化しますが、関数については、現在開いているファイルのみを処理します。
これは両方の世界の最良の部分を組み合わせるかもしれません。
Rust Roverとのメモリ使用量の比較は興味深いでしょう。
IDE GUI自体を除けば、RRの方がコンパクトになると予想します。
いくつかの機能はサポートされない可能性が高いです。
例えば、プロシージャマクロ呼び出しを介したビルドスクリプト/プロシージャマクロのサポートです。
私が物事を合理化したり、誤って記憶したりしているのかもしれませんが、私の記憶が正しければ、プロシージャマクロを追加したあたりから、不当に大きくなってきたように感じ始めました。
プロシージャマクロの展開は遅いです。
実際のコードを実行しているため、通常のIDEのトリックはできません。
そしてプロシージャマクロは大量のコードを生成します。
一度測定したことがありますが、rust-analyzerバイナリサイズの約30%がJSON解析コードに起因していました。
誰もコードを見ないなら、誰にも害を与えませんよね?
1つの可能なアプローチは、Sorbetのトリックを使うことです。
メタプログラミングを全く実行せず、代わりにプラグインインターフェースを使用して、それが何をしたかの効果を「説明」します。
serdeを実行する代わりに、空の本体を持つimp Serialize for T {}を注入するシムを追加します。
なぜかはわかりませんが、rust-analyzerでは、エージェントがコードを編集すると、インライヒントがずれることがあると観察しています。
rust-analyzerのコアデータモデルは、コードの一貫したスナップショットを常に観察することに非常に厳密であり、言語クライアントとサーバーが世界を共有し、厳密にシリアライズ可能なビューを持つことを保証するために最善を尽くしています。
LSPがそれを正しくすることを許可しないのは残念です。
古いDart Analyzerプロトコルとは異なり、健全なデータ同期が可能です。
しかし、ファイル監視の実装はいい加げです!
まず、2つのバックエンドがあります。
エディタに監視を依頼することもできますし、サーバーサイド監視を使用することもできます。
このオプションを変更して、それが役立つかどうかを確認してください?
しかし、私の記憶では、ネイティブウォッチャーのAPIは根本的に競合状態であり、それを正しくするために厄介なプラットフォーム固有の作業を行わなかったということです。
しかし、私が書きたい主なこと、そしてなぜ私が居心地の良いlobste.rsのテキストエリアからEmacsバッファの豪華な快適さに移動したのかというと、現在rust-analyzerはあの半分描かれた馬のミームのようなものであり、しかも馬の頭の半分だけだということです。
IntelliJの大きなアイデアは、そのPSI API(基本的に解決された型のAST)が実際にはインターフェースであり、複数のプロバイダーが存在することです。
そして典型的な使用法では、少なくとも3つのバックエンドが関与しています。
エディタで開かれており、ユーザーによって積極的に変更されているファイルの場合、PSIは具体的な構文木によってバックアップされます。
プロジェクトの残りのファイルの場合、PSIはいわゆるStub Treeによってバックアップされます。
これはディスク上のコンパクトな表現であり、ファイルの「外部から見える」部分のみを格納します(つまり、関数本体なし)。
ユーザーが新しいファイルに移動すると、そのPSIは透過的にスタブから構文木に切り替わります。
依存関係の場合、PSIはしばしばjavacによって生成されたコンパイル済みの.classファイルによってバックアップされます。
そこに移動すると、IDEはあなたのためにコードを逆コンパイルします!
これは、このようなものがどのように機能すべきかについての私の考えです。
rust-analyzerは、あなたがまだ見ていない6666の依存関係すべてにsalsaを使用すべきではありません。
それは単にrustcの.rmetaファイルを使用し、ユーザーが~/.cargo/registry/srcフォルダをいじり始めたときにのみ、透過的にsalsaに切り替えるべきです。
そのための前提条件は、Rustコードにアクセスするための抽象APIを定義することです。
それは常に計画であり、私たちはある時点でそれを開始しました。
https://hackmd.io/ytd82QNiT_Ku2XFr1EAtiQ
rmeta-transparent – ソースコードが一部のクレートで利用できない場合があります。
APIは、事前コンパイルされたrmetaファイルをインプットとしてサポートする必要があります。
しかし、その作業が完了したとは思えません。
これは依然として、最も簡単に手に入るスイカのように思えます。
世界を、氷山の先端のアーキテクチャ的に増分的な部分と、ほとんど読み取り専用で、ディスク上にあり、コンパクトで、暗く、湿った、サプライチェーン攻撃の繁殖地とに分割することです。
そのようなグランスアナライザーアーキテクチャは、私の意見では素晴らしいでしょう!