更新:この質問は、2012年6月8日の私のブログの主題でした。すばらしい質問をありがとう!
すばらしい質問です。私たちはあなたが提起する問題について長い間議論しました。
次の特性を持つデータ構造が必要です。
- 不変。
- 木の形。
- 子ノードから親ノードへの安価なアクセス。
- ツリー内のノードからテキスト内の文字オフセットにマップできます。
- 永続的。
永続 I能力を意味し、ツリー内の既存のノードのほとんどを再利用し、編集をテキストバッファに行われたときに。ノードは不変なので、それらを再利用するための障壁はありません。これはパフォーマンスのために必要です。キーを押すたびにファイルの膨大な数のウォッジを再解析することはできません。編集の影響を受けたツリーの部分のみを再レクスおよび再解析する必要があります。
これら5つすべてを1つのデータ構造に入れようとすると、すぐに問題が発生します。
- そもそもどうやってノードを作るのですか?親と子の両方が相互に参照し、不変なので、どちらが最初に構築されますか?
- その問題をなんとか解決できたとしたら、どうすればそれを永続化できますか?別の親で子ノードを再利用することはできません。これは、新しい親があることを子に伝えることになるためです。しかし、子供は不変です。
- その問題を解決できたとしましょう。新しい文字を編集バッファーに挿入すると、そのポイントの後の位置にマップされているすべてのノードの絶対位置が変化します。編集を行うとほとんどのノードのスパンが変更される可能性があるため、永続的なデータ構造を作成するのは非常に困難です。
しかし、Roslynチームでは、不可能なことを日常的に行っています。実際には、2つの解析ツリーを保持することで不可能を実現しています。「グリーン」ツリーは不変で永続的であり、親参照がなく、「ボトムアップ」で構築され、すべてのノードはその幅を追跡しますが、絶対位置は追跡しません。編集が発生すると、編集の影響を受けた緑のツリーの部分のみが再構築されます。これは通常、ツリー内の解析ノードの総数の約O(log n)です。
「赤」の木は、緑の木の周りに構築される不変のファサードです。オンデマンドで「トップダウン」で構築され、編集ごとに破棄されます。親参照は、ツリーを上から下に降りていくときにオンデマンドで製造することで計算されます。また、下降すると、幅から絶対位置を計算して絶対位置を生成します。
ユーザーであるあなたには、赤い木しか見えません。緑の木は実装の詳細です。解析ノードの内部状態を覗いてみると、実際には別のタイプの別の解析ノードへの参照があることがわかります。これが緑のツリーノードです。
ちなみに、これらは「赤/緑の木」と呼ばれています。これらは、設計会議でデータ構造を描画するために使用したホワイトボードマーカーの色でした。色に他の意味はありません。
この戦略の利点は、不変性、永続性、親参照など、これらすべての優れた機能を利用できることです。コストは、このシステムが複雑であり、「赤い」ファサードが大きくなると、大量のメモリを消費する可能性があることです。現在、利益を失うことなくコストを削減できるかどうかを確認するための実験を行っています。