dowel

ADR-0012: ストアへ格納するのは評価結果のみとし、診断を持つファイルは格納しない

状態: Accepted

文脈

常駐デーモンを持たない(ADR-0002)ため、プロセス内のメモ表は 実行の終わりに失われる。プロセスを跨いだ再利用は永続化ストア (20-architecture.md 5節)が担う。

ストアの機構は実装済みである。追記専用の値ログ、原子的に差し替えるインデックス、 単一書き手の制限、形式版ごとのディレクトリ、入力の stat 走査による変更検出。 現在これを使っているのは入力の記録だけであり、値ログは空のままである。

格納の候補は2つある(99-open-questions.md Q9)。

対象 省けるもの
Evaluated(ファイル単位) 字句解析・構文解析・評価
Interface / CompileEnv(ターゲット単位) 併合

決定

Evaluated のみを格納する。ターゲット単位の派生はプロセス内のメモに留める。

格納の対象は、診断を1件も出さずに評価できたファイルに限る。

復元の判定は本文の指紋の一致による。復元した文書の FileId が問い合わせた ファイルと異なる場合は使わない。

根拠

ターゲット単位の派生を格納しても評価を省けない。 interfacecompile_envDeclaredDeps を入力に取る。Declared はターゲットの宣言を評価した結果から 作られるため、これを組み立てるには評価が要る。したがって派生だけを格納しても 併合を省けるだけであり、その前段の字句解析・構文解析・評価は毎回走る。 両方を格納する案は、評価を省く目的においては Evaluated の格納と等価であり、 併合の分だけ格納する対象が増える。

診断を持つ値を格納しないのは、診断の識別子が &'static str であるためである。 復元には識別子を静的な文字列へ戻す必要があり、既知の識別子の一覧を実行時に 持つことになる。この一覧は診断を足すたびに更新が要り、更新漏れを防ぐために 別の検査を要する。網羅の追跡(51-testing.md)と同じ対象に 2つ目の台帳を持つことになる。

診断を持つファイルを毎回評価し直す代償は、ADR-0011 が 診断を指紋に含めた判断と同じ性質を持つ。誤りや警告が残っている間、利用者は編集を 繰り返している最中であり、その間の再利用の利得は小さい。

復元後に FileId を照合するのは、鍵の衝突を値の側で検出するためである。 ストアの鍵はハッシュであり、衝突しないことを形式が保証していない。文書は自身の FileId を持つため、照合の費用は比較1回である。

却下した案

両方を格納する。 上記のとおり、評価を省く効果は Evaluated の格納で尽きる。 併合の費用はターゲット数に比例し、評価の費用はマニフェストのバイト数に比例する。 後者が支配的である間、前者を格納する利得は測れない。将来 interface が ツールチェーンのプローブ結果を入力に取るようになれば再検討の対象になる。

診断も直列化する。 識別子の一覧を実行時に持つことになる。上記のとおり、 台帳が増える。

識別子を Box::leak で復元する。 一覧を持たずに済むが、ストアの内容が 壊れている場合に任意のバイト列が識別子になる。診断の識別子は利用者が --deny 等で指定しうる安定識別子であり、由来を実行ファイル内に限る。

値ログにファイル単位ではなくクエリ単位で書く。 現在の Evaluated は ファイル単位のクエリであるため、両者は一致する。区別が生じるのは ターゲット単位の派生を格納する場合であり、それを却下した以上は選択肢にならない。

影響

query::evaluated は復元元を引数に取る。Session はストアを開いて渡し、 実行の終わりに新しく計算した分を書く。

復元が起きた場合、Parsed のメモは作られない。構文木を要する経路 (言語サーバのホバー)は同一プロセス内で解析するため、影響を受けない。

鍵と指紋の算出は DefaultHasher による。この実装は Rust の版を跨いで 同一であることを保証していない。変わった場合に起きるのは鍵の不一致と 指紋の不一致であり、いずれも再計算に落ちる。失うのは再利用の利得だけであり、 結果は変わらない。古い記録は Store::gc の 対象ではないため、形式版を上げるまで残る。

検査は an_unchanged_manifest_is_restored_from_the_storeediting_a_manifest_makes_the_store_recompute_itscenario.rs)が対で行う。 前者だけでは、そもそも評価を問い合わせていない状態でも通る。

格納が起きる実行は、インデックスの差し替えに伴う sync_data 2回の分だけ遅くなる。 計測は 91-implementation-status.md「計測」にある。 費用はマニフェストを変更した実行にのみ生じる。書くものが無い実行では 差し替えを行わない。

同期を省けばこの費用は消える。復元できない値は無いものとして扱われるため (codec 冒頭)、同期を省いても誤った結果にはならない。ただし 20-architecture.md 5.3 が述べる担保の一角を外すことになるため、 本 ADR では採らない。判断には、短縮の側が規模に比例することを示す計測が要る。