200 lines
5.2 KiB
Markdown
200 lines
5.2 KiB
Markdown
# Phase 11.5a: Write Barrier除去によるGC最適化
|
||
|
||
## 🎯 目標
|
||
JITコンパイル時にescape analysisを行い、不要なwrite barrierを除去してGC性能を大幅に向上させる。
|
||
|
||
## 📊 現状の問題
|
||
|
||
### 現在のVM実装
|
||
```rust
|
||
// すべてのrefset操作でbarrierが呼ばれる
|
||
pub fn execute_ref_set(&mut self, reference: ValueId, field: &str, value: ValueId)
|
||
-> Result<ControlFlow, VMError> {
|
||
// ... 値の設定 ...
|
||
|
||
// 常にwrite barrierが実行される
|
||
gc_write_barrier_site(&self.runtime, "RefSet");
|
||
Ok(ControlFlow::Continue)
|
||
}
|
||
```
|
||
|
||
### オーバーヘッド
|
||
- 単純な代入でも毎回barrier呼び出し
|
||
- Stack上のローカル変数でも不要にbarrier
|
||
- ループ内での大量のbarrier呼び出し
|
||
|
||
## 🚀 実装計画
|
||
|
||
### Step 1: Escape Analysis基盤
|
||
```rust
|
||
// mir/escape_analysis.rs
|
||
pub struct EscapeAnalysis {
|
||
// allocation site追跡
|
||
allocations: HashMap<ValueId, AllocInfo>,
|
||
// escape状態
|
||
escapes: HashSet<ValueId>,
|
||
// 解析結果キャッシュ
|
||
cache: HashMap<FunctionId, EscapeInfo>,
|
||
}
|
||
|
||
#[derive(Debug)]
|
||
struct AllocInfo {
|
||
location: BasicBlockId,
|
||
kind: AllocKind,
|
||
size: Option<usize>,
|
||
}
|
||
|
||
enum AllocKind {
|
||
NewBox, // new StringBox()
|
||
ArrayNew, // []
|
||
RefNew, // ユーザー定義Box
|
||
}
|
||
```
|
||
|
||
### Step 2: MIR解析
|
||
```rust
|
||
impl EscapeAnalysis {
|
||
/// 関数内でのescape解析
|
||
pub fn analyze_function(&mut self, func: &MirFunction) -> EscapeInfo {
|
||
// 1. allocation site収集
|
||
for (bb_id, bb) in &func.basic_blocks {
|
||
for inst in &bb.instructions {
|
||
match inst {
|
||
MirInstruction::NewBox { dst, .. } |
|
||
MirInstruction::ArrayNew { dst, .. } |
|
||
MirInstruction::RefNew { dst, .. } => {
|
||
self.allocations.insert(*dst, AllocInfo {
|
||
location: bb_id,
|
||
kind: self.classify_alloc(inst),
|
||
size: self.estimate_size(inst),
|
||
});
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 2. escape point検出
|
||
self.find_escape_points(func);
|
||
|
||
// 3. 結果集計
|
||
EscapeInfo {
|
||
non_escaping: self.collect_non_escaping(),
|
||
barrier_sites: self.collect_barrier_sites(),
|
||
}
|
||
}
|
||
|
||
fn find_escape_points(&mut self, func: &MirFunction) {
|
||
// return文でのescape
|
||
// 関数引数としてのescape
|
||
// グローバル変数へのescape
|
||
// プラグイン呼び出しでのescape
|
||
}
|
||
}
|
||
```
|
||
|
||
### Step 3: JIT統合
|
||
```rust
|
||
// jit/lower/builder.rs
|
||
impl<'a> LoweringBuilder<'a> {
|
||
fn emit_ref_set(&mut self, reference: Value, field: &str, value: Value) {
|
||
// escape解析結果を確認
|
||
let needs_barrier = self.escape_info
|
||
.map(|info| info.needs_barrier(reference))
|
||
.unwrap_or(true); // 解析なしなら保守的にbarrier
|
||
|
||
if needs_barrier {
|
||
// barrierあり
|
||
self.emit_gc_barrier(BarrierKind::Write);
|
||
} else {
|
||
// barrier除去!
|
||
if self.config.trace_opt {
|
||
eprintln!("[JIT] barrier removed at {:?}", self.current_location());
|
||
}
|
||
}
|
||
|
||
// 実際のstore操作
|
||
self.emit_store(reference, field, value);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Step 4: 最適化レベル設定
|
||
```rust
|
||
// 環境変数で制御
|
||
NYASH_JIT_ESCAPE_ANALYSIS=1 # escape analysis有効化
|
||
NYASH_JIT_BARRIER_OPT=1 # barrier最適化有効化
|
||
NYASH_JIT_BARRIER_STATS=1 # 統計出力
|
||
```
|
||
|
||
## 📈 期待される効果
|
||
|
||
### ベンチマーク例
|
||
```nyash
|
||
// 大量のローカル変数操作
|
||
function processData(n) {
|
||
local sum = 0
|
||
local temp = new MapBox()
|
||
|
||
loop(i < n) {
|
||
temp.set(i, i * 2) // escape analysisでbarrier除去
|
||
sum = sum + temp.get(i)
|
||
i = i + 1
|
||
}
|
||
|
||
return sum
|
||
}
|
||
```
|
||
|
||
### 性能改善予測
|
||
- ローカル変数操作: 90%以上のbarrier除去
|
||
- ループ内操作: 80%以上の高速化
|
||
- 全体的なGCオーバーヘッド: 50%削減
|
||
|
||
## 🔍 検証方法
|
||
|
||
### 1. Barrier統計
|
||
```json
|
||
{
|
||
"total_barriers": 10000,
|
||
"removed_barriers": 8500,
|
||
"removal_rate": 0.85,
|
||
"sites": {
|
||
"RefSet": { "total": 5000, "removed": 4800 },
|
||
"ArraySet": { "total": 3000, "removed": 2500 },
|
||
"MapSet": { "total": 2000, "removed": 1200 }
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 性能測定
|
||
```bash
|
||
# barrier最適化なし
|
||
NYASH_JIT_ESCAPE_ANALYSIS=0 ./target/release/nyash --benchmark
|
||
|
||
# barrier最適化あり
|
||
NYASH_JIT_ESCAPE_ANALYSIS=1 ./target/release/nyash --benchmark
|
||
```
|
||
|
||
## 🚧 実装上の注意点
|
||
|
||
1. **保守的な解析**
|
||
- 不明な場合は必ずbarrierを残す
|
||
- プラグイン境界では常にbarrier
|
||
|
||
2. **デバッグ性**
|
||
- 除去したbarrierサイトを記録
|
||
- GCエラー時の診断情報
|
||
|
||
3. **段階的実装**
|
||
- まずローカル変数のみ
|
||
- 次にループ不変式
|
||
- 最後に関数間解析
|
||
|
||
## 🎉 完了基準
|
||
|
||
- [ ] Escape analysis基本実装
|
||
- [ ] MIR解析パス追加
|
||
- [ ] JIT統合
|
||
- [ ] ベンチマーク50%改善
|
||
- [ ] ドキュメント更新 |