浏览器 vs 服务端

同一份 Rust 代码,一边编译成 WebAssembly 在浏览器里跑,一边编译成原生程序在服务端多线程跑

① 同一份 Rust 代码:浏览器(WebAssembly)对比服务端(原生)

两边都是单线程,运行同一份 Rust 源码、同样的优化级别(opt-level "s")。服务端的「计算耗时」由程序自己计时,「总耗时」是页面看到的整个请求(启动程序、生成输入、网络往返)。先跑浏览器、再跑服务端,免得同一台电脑上互相抢 CPU。

② 服务端多线程渲染,按行带流式回传

服务端:未运行
浏览器:未运行

需要本地服务:serve.py … --mcp mcp.config.json --compute | 左侧色条:每条行带由哪个服务端线程渲染

📖 原理说明

同一份 Rust 源码可以编译成两种东西:wasm32-unknown-unknown 目标的 WebAssembly,交给浏览器执行;或者当前机器的原生程序,由操作系统直接执行。本页把 SHA-256、DEFLATE、数独求解和路径追踪这几个示例的 crate 原样编译成服务端程序 compute,和浏览器里的 wasm 跑同样的输入,比较耗时,并逐位比对结果,确认两边真的是同一份代码。

🧮算法原理

总耗时 = 启动程序 + 生成输入 + 计算 + 网络往返服务端的「计算耗时」只算中间那一项,和浏览器的计时口径相同
加速比 ≈ 1 / ((1 − p) + p / n)Amdahl 定律:p 为可并行部分,n 为线程数;路径追踪的各行互不依赖,p 接近 1
同一份代码
服务端程序 crates/native/compute 直接依赖 sha256、compress、sudoku、pathtracer 这几个示例 crate(它们因此同时编译成 cdylib 和 rlib)。两边用同样的优化级别(opt-level "s")编译,输入由同一个 xorshift32 生成器产生,所以哈希、压缩结果、数独的搜索步数都必须逐位相同,页面会检查。
WebAssembly 与原生代码的差距
wasm 运行在沙箱里:每次内存访问都要做边界检查(或依赖保护页),只能用 wasm 标准里的指令(SIMD 只有 128 位,本页的基准没有开 SIMD),函数调用和间接跳转也要经过类型检查。现代浏览器的 JIT 能把大部分开销压得很低,差距通常在几十个百分点以内,具体取决于算法和浏览器。
确定性的并行渲染
路径追踪里每一行、每一遍采样都有自己的随机数种子,行与行互不依赖。服务端把图像切成 16 行一条的行带,多个线程从同一个计数器领取行带,谁领到谁算;每个像素的样本仍按遍数顺序累加,所以无论几个线程、按什么顺序完成,结果都和浏览器单线程逐字节相同。
流式回传
每条行带算完就立刻编码成 base64 写成一行 JSON,compute_bridge.py 把它转成服务器推送事件(SSE)发给页面,页面用 fetch 流式读取并当场画出来。左侧的色条标出每条行带由哪个线程完成,可以看到行带是乱序到达的。

为什么不用 EventSource 接收?它在连接结束时会自动重连——这里等于再发起一次渲染;而且拿不到 HTTP 状态码(429 繁忙、401 未登录)。用 fetch 读流两个问题都没有。

🔄Rust 与 JavaScript 的分工

  1. JS基准:先在浏览器里生成同样的输入并计时运行 wasm,再 POST /api/compute/bench;渲染:GET /api/compute/render 流式读取行带。
  2. Rust服务端 compute bench 调用各 crate 的函数并自己计时;compute render 用标准库线程渲染行带,每条一行 JSON 写到标准输出。
  3. JScompute_bridge.py 校验参数、限制并发(最多 2 个)、超时后结束进程;页面关闭时也立刻结束渲染进程。
  4. Rust浏览器一侧的渲染在 Web Worker 里调用单线程的 pathtracer wasm,画完后和服务端的图逐像素比对。

计算接口和 MCP 调试台用同一套访问控制:本机凭令牌,通过域名访问需要登录,因为它消耗的是这台机器的 CPU。

⚡性能要点

  • 单线程基准比的是同一份代码在两种环境下的执行效率;网络和启动进程的开销单独列在「总耗时」里,数据量小的时候它往往比计算本身还大。
  • 渲染时服务端的线程数可以调:线程越多越快,直到用满 CPU 核心;分辨率越高、采样越多,服务端多线程的优势越明显。
  • 同一台电脑上两边会抢 CPU,所以基准先跑浏览器、再跑服务端;渲染对比时也建议一次只跑一边。

源码crates/native/compute/src/lib.rs服务端程序crates/graphics/pathtracer/src/lib.rsTracer:行带渲染scripts/compute_bridge.py参数校验、并发与超时www/server-compute/index.jswww/server-compute/render-worker.js