{
  "lead": "同一份 Rust 源码可以编译成两种东西：<code>wasm32-unknown-unknown</code> 目标的 WebAssembly，交给浏览器执行；或者当前机器的原生程序，由操作系统直接执行。本页把 SHA-256、DEFLATE、数独求解和路径追踪这几个示例的 crate 原样编译成服务端程序 <code>compute</code>，和浏览器里的 wasm 跑同样的输入，比较耗时，并逐位比对结果，确认两边真的是同一份代码。",
  "formulas": [
    ["总耗时 = 启动程序 + 生成输入 + 计算 + 网络往返", "服务端的「计算耗时」只算中间那一项，和浏览器的计时口径相同"],
    ["加速比 ≈ 1 / ((1 − p) + p / n)", "Amdahl 定律：p 为可并行部分，n 为线程数；路径追踪的各行互不依赖，p 接近 1"]
  ],
  "terms": [
    ["同一份代码", "服务端程序 <code>crates/native/compute</code> 直接依赖 <code>sha256</code>、<code>compress</code>、<code>sudoku</code>、<code>pathtracer</code> 这几个示例 crate（它们因此同时编译成 <code>cdylib</code> 和 <code>rlib</code>）。两边用同样的优化级别（opt-level \"s\"）编译，输入由同一个 xorshift32 生成器产生，所以哈希、压缩结果、数独的搜索步数都必须逐位相同，页面会检查。"],
    ["WebAssembly 与原生代码的差距", "wasm 运行在沙箱里：每次内存访问都要做边界检查（或依赖保护页），只能用 wasm 标准里的指令（SIMD 只有 128 位，本页的基准没有开 SIMD），函数调用和间接跳转也要经过类型检查。现代浏览器的 JIT 能把大部分开销压得很低，差距通常在几十个百分点以内，具体取决于算法和浏览器。"],
    ["确定性的并行渲染", "路径追踪里每一行、每一遍采样都有自己的随机数种子，行与行互不依赖。服务端把图像切成 16 行一条的行带，多个线程从同一个计数器领取行带，谁领到谁算；每个像素的样本仍按遍数顺序累加，所以无论几个线程、按什么顺序完成，结果都和浏览器单线程逐字节相同。"],
    ["流式回传", "每条行带算完就立刻编码成 base64 写成一行 JSON，<code>compute_bridge.py</code> 把它转成服务器推送事件（SSE）发给页面，页面用 <code>fetch</code> 流式读取并当场画出来。左侧的色条标出每条行带由哪个线程完成，可以看到行带是乱序到达的。"]
  ],
  "terms_notes": [
    "为什么不用 EventSource 接收？它在连接结束时会自动重连——这里等于再发起一次渲染；而且拿不到 HTTP 状态码（429 繁忙、401 未登录）。用 <code>fetch</code> 读流两个问题都没有。"
  ],
  "flow": [
    ["js", "基准：先在浏览器里生成同样的输入并计时运行 wasm，再 <code>POST /api/compute/bench</code>；渲染：<code>GET /api/compute/render</code> 流式读取行带。"],
    ["rust", "服务端 <code>compute bench</code> 调用各 crate 的函数并自己计时；<code>compute render</code> 用标准库线程渲染行带，每条一行 JSON 写到标准输出。"],
    ["js", "<code>compute_bridge.py</code> 校验参数、限制并发（最多 2 个）、超时后结束进程；页面关闭时也立刻结束渲染进程。"],
    ["rust", "浏览器一侧的渲染在 Web Worker 里调用单线程的 <code>pathtracer</code> wasm，画完后和服务端的图逐像素比对。"]
  ],
  "flow_notes": [
    "计算接口和 MCP 调试台用同一套访问控制：本机凭令牌，通过域名访问需要登录，因为它消耗的是这台机器的 CPU。"
  ],
  "perf": [
    "单线程基准比的是同一份代码在两种环境下的执行效率；网络和启动进程的开销单独列在「总耗时」里，数据量小的时候它往往比计算本身还大。",
    "渲染时服务端的线程数可以调：线程越多越快，直到用满 CPU 核心；分辨率越高、采样越多，服务端多线程的优势越明显。",
    "同一台电脑上两边会抢 CPU，所以基准先跑浏览器、再跑服务端；渲染对比时也建议一次只跑一边。"
  ],
  "src": [
    ["crates/native/compute/src/lib.rs", "服务端程序"],
    ["crates/graphics/pathtracer/src/lib.rs", "Tracer：行带渲染"],
    ["scripts/compute_bridge.py", "参数校验、并发与超时"],
    ["www/server-compute/index.js", ""],
    ["www/server-compute/render-worker.js", ""]
  ]
}
