🔀 Rust 并行优势

Rust 的所有权系统保证线程安全,编译时检测数据竞争:

🔒 编译时保证

  • 不可能发生数据竞争
  • Send trait 保证线程安全传递
  • Sync trait 保证线程安全共享

📊 使用 rayon 并行迭代

rust
use neon::prelude::*;
use rayon::prelude::*;

fn parallel_process(mut cx: FunctionContext) -> JsResult {
    // 获取输入数组
    let input: Vec = cx.argument::(0)?
        .to_vec(&mut cx)?
        .iter()
        .map(|v| v.downcast::(&mut cx).unwrap().value(&mut cx) as i32)
        .collect();
    
    // 并行处理
    let result: Vec = input.into_par_iter()
        .map(|x| x * x)  // 并行计算平方
        .collect();
    
    // 返回结果
    let arr = cx.empty_array();
    for (i, val) in result.iter().enumerate() {
        arr.set(&mut cx, i as u32, cx.number(*val as f64))?;
    }
    
    Ok(arr)
}

📡 Channel 通信

跨线程通信使用 Channel:

rust
use neon::prelude::*;
use std::thread;
use std::sync::mpsc;

fn background_task(mut cx: FunctionContext) -> JsResult {
    let channel = cx.channel();
    let (tx, rx) = mpsc::channel();
    
    // 启动后台线程
    thread::spawn(move || {
        let result = expensive_computation();
        tx.send(result).unwrap();
    });
    
    // 主线程继续
    // 可以定期检查 rx 或使用 callback
    
    Ok(cx.undefined())
}

⚠️ 注意事项

🚫 不要在非主线程访问 JS 对象

  • JavaScript 对象只能在主线程访问
  • 使用 Channel 跨线程传递数据
  • 使用 cx.channel() 回调主线程
rust
// ❌ 错误:在子线程访问 JS 对象
fn bad_example(mut cx: FunctionContext) -> JsResult {
    let obj = cx.argument::(0)?;
    thread::spawn(move || {
        // 错误!obj 不能跨线程传递
        let _ = obj.get(&mut cx, "key");
    });
    Ok(cx.undefined())
}

// ✅ 正确:先提取数据
fn good_example(mut cx: FunctionContext) -> JsResult {
    let obj = cx.argument::(0)?;
    let data = obj.get::(&mut cx, "key")?.value(&mut cx);
    
    thread::spawn(move || {
        // 使用 data 字符串
        println!("{}", data);
    });
    Ok(cx.undefined())
}