iOS15.1移动Safari创建Blob引发WebSocket网络进程崩溃如何解决?
根因说明
这是iOS 15.0~15.2版本移动Safari的已知内核bug:高频创建Blob且未主动释放关联内存、同时WebSocket开启perMessageDeflate压缩的场景下,会导致网络进程内存持续泄漏,最终触发进程崩溃,iOS14不存在该内核问题。
可行解决方案
- 方案1:移除冗余Blob中转逻辑,直接解码ArrayBuffer渲染(最优)
Canvas支持直接渲染ImageBitmap对象,调整逻辑后既可以减少性能损耗,也能规避Blob相关的内存泄漏,同时初始化socket时关闭压缩配置即可解决问题,示例代码如下:
// 初始化socket时关闭perMessageDeflate,规避WebSocket压缩的内存泄漏 const socket = io(process.env.SERVER ?? "", { transports: ["websocket"], perMessageDeflate: false }); socket.on("connect", () => { socket.emit("subscribe", { topic: "rgb_image" }); }); socket.on("rgb_image", async (msg, ack) => { // 直接从接收的ArrayBuffer创建可渲染的ImageBitmap const imageBitmap = await createImageBitmap(new Blob([msg.data], { type: "image/jpeg" })); // 渲染到Canvas const ctx = canvas.getContext('2d'); ctx.drawImage(imageBitmap, 0, 0); // 主动释放ImageBitmap占用的显存,完全避免内存堆积 imageBitmap.close(); });
方案2:兜底重连机制
如果业务逻辑必须保留原有Blob转换逻辑,可以设置帧计数阈值,每处理15000帧(低于你实测的20000次崩溃阈值)就主动断开socket重连,主动释放网络进程关联的内存,避免堆到崩溃阈值。方案3:低版本兼容方案
如果需要兼容不支持createImageBitmap的旧版本设备,也可以将图像数据转成base64格式后赋值给Image对象渲染,虽然性能略低于ImageBitmap方案,但可以完全规避Blob和WebSocket压缩的内存泄漏问题。
内容的提问来源于stack exchange,提问作者lemonad
相关产品推荐
相关产品推荐

