把解析好的大数组交给 worker,主线程在 postMessage 这一行同步卡了 900ms。worker 收到后内存又涨了 80MB,前后打的时间戳差值全在调用上。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,postMessage 默认走结构化克隆,对象要完整序列化一份再反序列化,CPU 和内存都翻倍。对象越大这次拷贝越接近全量复制,主线程也躲不开。
「postMessage 序列化开销」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。
const { Worker } = require('worker_threads');
const buf = new Float64Array(1e7);
worker.postMessage({ buf }, [buf.buffer]);
console.log(buf.length);
权限不要一口气开到最大,先加到够用再往上试,范围小才好收。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。
具体做法是,大块二进制改用 SharedArrayBuffer 共享 不做拷贝;传 TypedArray 时带 transferList 转移所有权 原线程立刻失效;只传必要字段 别把整个响应对象丢过去;用 performance.now 量调用前后的耗时。
最后用这个标准收尾,postMessage 耗时从 900ms 降到个位数毫秒 转移之后主线程的 buf.length 变成 0。
