Files
hakorune/docs/phases/phase-11.5/11.5c-COROUTINE-ASYNC.md

6.9 KiB
Raw Blame History

Phase 11.5c: Coroutine実装による非同期処理の完成

🎯 目標

async/await構文を追加し、JITレベルでcoroutineをstate machineに変換して高性能な非同期処理を実現する。

📊 現状と目標

現在の非同期処理

// nowait文スレッドベース
nowait result = heavyComputation()
// ...
local value = wait result  // FutureBoxから取得

目標の構文

// async/awaitcoroutineベース
async function fetchData(url) {
    local response = await httpGet(url)
    local json = await response.json()
    return json.data
}

// 複数の非同期処理
async function fetchAll(urls) {
    local promises = []
    loop(url in urls) {
        promises.push(fetchData(url))
    }
    return await Promise.all(promises)
}

🚀 実装計画

Step 1: AST拡張

// ast.rs
#[derive(Debug, Clone)]
pub enum ASTNode {
    // 既存
    Function { name: String, params: Vec<String>, body: Box<ASTNode> },
    
    // 新規追加
    AsyncFunction { 
        name: String, 
        params: Vec<String>, 
        body: Box<ASTNode> 
    },
    AwaitExpression { 
        expression: Box<ASTNode> 
    },
}

Step 2: MIR Coroutine命令

// mir/instruction.rs
pub enum MirInstruction {
    // 既存命令...
    
    // Coroutine関連
    /// Coroutine生成
    CoroutineCreate { 
        dst: ValueId,
        func: FunctionId,
        captures: Vec<ValueId>,
    },
    
    /// Yield pointawait
    CoroutineYield {
        value: ValueId,
        resume_label: BasicBlockId,
    },
    
    /// Coroutine再開
    CoroutineResume {
        dst: Option<ValueId>,
        coroutine: ValueId,
        value: Option<ValueId>,
    },
    
    /// Promise結合
    PromiseAll {
        dst: ValueId,
        promises: Vec<ValueId>,
    },
}

Step 3: State Machine変換

// mir/coroutine_transform.rs
pub struct CoroutineTransform {
    state_enum: HashMap<FunctionId, StateEnum>,
}

/// async関数をstate machineに変換
impl CoroutineTransform {
    pub fn transform_async_function(&mut self, 
        func: &MirFunction
    ) -> MirFunction {
        // 1. await pointsを収集
        let await_points = self.collect_await_points(func);
        
        // 2. State enum生成
        let states = self.generate_states(await_points);
        
        // 3. State machine関数生成
        let state_machine = self.build_state_machine(func, states);
        
        // 4. Coroutine wrapper生成
        self.wrap_as_coroutine(state_machine)
    }
    
    fn build_state_machine(&self, 
        func: &MirFunction, 
        states: Vec<State>
    ) -> MirFunction {
        // switch(state) {
        //   case State0: ... goto await1 or return
        //   case State1: ... goto await2 or return
        //   ...
        // }
        
        let mut builder = MirBuilder::new();
        
        // Coroutine state
        let state_var = builder.emit_local("state");
        let locals = builder.emit_local("locals");
        
        // Main dispatch loop
        let loop_bb = builder.create_block();
        builder.emit_jump(loop_bb);
        
        builder.switch_to_block(loop_bb);
        let state = builder.emit_load(state_var);
        
        // State dispatch
        for (i, state) in states.iter().enumerate() {
            let state_bb = builder.create_block();
            builder.emit_case(state.id, state_bb);
            
            builder.switch_to_block(state_bb);
            self.emit_state_code(&mut builder, state);
        }
        
        builder.build()
    }
}

Step 4: JIT Coroutine最適化

// jit/lower/coroutine.rs
impl<'a> LoweringBuilder<'a> {
    /// Coroutineのstack switching最適化
    fn emit_coroutine_switch(&mut self, 
        from: Value, 
        to: Value
    ) {
        if self.config.use_fast_switch {
            // レジスタのみ保存(最適化)
            self.emit_save_registers();
            self.emit_switch_stack(to);
            self.emit_restore_registers();
        } else {
            // フルコンテキスト保存
            self.emit_full_context_save(from);
            self.emit_full_context_restore(to);
        }
    }
    
    /// Inline可能なawaitの検出
    fn try_inline_await(&mut self, 
        await_expr: &MirInstruction
    ) -> Option<Value> {
        // Promise.resolvedなら即値返却
        if self.is_resolved_promise(await_expr) {
            return Some(self.emit_immediate_value());
        }
        
        // 小さなasync関数ならインライン化
        if self.is_small_async(await_expr) {
            return Some(self.inline_async_call(await_expr));
        }
        
        None
    }
}

Step 5: ランタイムサポート

// boxes/promise_box.rs
pub struct PromiseBox {
    state: Arc<Mutex<PromiseState>>,
    base: BoxBase,
}

enum PromiseState {
    Pending(Vec<Box<dyn FnOnce(Box<dyn NyashBox>)>>),
    Resolved(Box<dyn NyashBox>),
    Rejected(String),
}

impl PromiseBox {
    pub fn all(promises: Vec<Box<PromiseBox>>) -> Box<PromiseBox> {
        // 全Promise完了待ち
        let result = PromiseBox::new();
        let remaining = Arc::new(AtomicUsize::new(promises.len()));
        
        for (i, promise) in promises.iter().enumerate() {
            promise.then(move |value| {
                // 結果収集
                if remaining.fetch_sub(1, Ordering::SeqCst) == 1 {
                    result.resolve(collected_values);
                }
            });
        }
        
        Box::new(result)
    }
}

📈 期待される効果

パフォーマンス比較

// Before: Thread-based
nowait results = []
loop(url in urls) {
    nowait r = httpGet(url)  // 新スレッド生成
    results.push(r)
}

// After: Coroutine-based
async function fetchAll(urls) {
    return await Promise.all(
        urls.map(url => httpGet(url))  // Stack switching only
    )
}

改善予測

  • メモリ使用量: 1/100スレッドstack vs coroutine state
  • コンテキストスイッチ: 1000倍高速
  • 同時接続数: 10,000+対応可能

🔍 検証方法

1. Coroutine統計

{
  "total_coroutines": 10000,
  "active_coroutines": 500,
  "yield_count": 50000,
  "average_yield_ns": 100,
  "stack_memory_mb": 10
}

2. ベンチマーク

# 10000並行リクエスト
./target/release/nyash bench/async_stress.nyash

# メモリプロファイル
NYASH_COROUTINE_STATS=1 ./target/release/nyash bench/async_memory.nyash

🚧 実装上の注意点

  1. Stack管理

    • Segmented stack対応
    • Stack overflow検出
    • GC root scanning
  2. エラー伝播

    • async境界でのエラー
    • Promise rejection chain
  3. デバッグ対応

    • async stack trace
    • Coroutine状態可視化

🎉 完了基準

  • async/await構文実装
  • MIR coroutine変換
  • JIT最適化
  • Promise/PromiseBox実装
  • 10000並行処理ベンチマーク達成