百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

postMessage 性能飙升500倍,内存占用锐减95%?

myzbx 2025-10-19 10:03 19 浏览

家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。

postMessage 是 JavaScript 在多个工作线程之间发送数据的最常用方法,在 Bun v1.2.21 中,postMessage(string) 的性能做到了几乎与字符串大小无关,这对于多线程 JavaScript 服务器和命令行界面 (CLI) 来说是一项重大的性能改进。

 // 主页面发送消息和接收消息
function sendMessage() {
    document.getElementById('iframe').contentWindow.postMessage('你好,子页面!', '*');
}
window.addEventListener('message', function(event) {
    document.getElementById('messages').innerHTML += '<p>收到: ' + event.data + '</p>';
});
// 子页面发送消息和接收消息
function sendMessage() {
    window.parent.postMessage('你好,父页面!', '*');
}
window.addEventListener('message', function(event) {
    document.getElementById('messages').innerHTML += '<p>收到: ' + event.data + '</p>';
});

通过避免对可以安全跨线程共享的字符串进行序列化,postMessage 速度提高了 500 倍,并且在此基准测试中使用的峰值内存减少了约 22 倍。

当开发者在工作线程之间发送字符串时,优化会自动启动:

// 在worker之间发送数据
const response = await fetch("https://api.example.com/data");
const json = await response.text();
postMessage(json); 
// 大型字符串带来500x的性能提升

这对于在工作线程之间传递大型 JSON 的应用程序特别有用,例如: API 服务器、数据处理管道和实时应用程序。

如何在 JavaScriptCore 中实现这一点

postMessage 通常使用结构化克隆算法对数据进行序列化,然后再将其发送到另一个线程。这意味着需要将字符串的每个字节复制到一个新的缓冲区,然后在另一端对其进行反序列化。

// 原始对象
const original = {
    name: "张三",
    age: 25,
    hobbies: ["读书", "游泳"],
    details: {
        city: "北京"
    }
};
// 使用 structuredClone 深拷贝
const cloned = structuredClone(original);
// 修改克隆对象,不会影响原始对象
cloned.name = "李四";
cloned.hobbies.push("编程");
cloned.details.city = "上海";
console.log("原始对象:", original);
// 输出: { name: "张三", age: 25, hobbies: ["读书", "游泳"], details: { city: "北京" } }
console.log("克隆对象:", cloned);
// 输出: { name: "李四", age: 25, hobbies: ["读书", "游泳", "编程"], details: { city: "上海" } }

但问题是,在 JavaScriptCore(Bun 使用的引擎)中,字符串已经是线程安全的引用计数对象。字符串数据本身在创建后是不可变的,并且引用计数使用 std::atomic:

class StringImplShape {
    std::atomic<unsigned> m_refCount;  // 线程安全
    unsigned m_length;                  // 不可变
    union {
        const LChar* m_data8;           // 不可变
        const char16_t* m_data16;       // 不可变
    };
    mutable unsigned m_hashAndFlags;    // 唯一可变的部分
};

因此,如果字符串已经是线程安全的,那么在同一进程的线程之间发送时可以有效避免序列化

寻找快速路径

并非所有字符串都能安全地共享,主要包括三种需要序列化的类型:

  • 原子字符串 :线程本地属性名称和Symbol
  • 子字符串 :指向具有复杂生命周期的其他字符串
  • Rope 字符串 : 由“foo”+“bar”或 .slice() 等操作创建的字符串

对于其他字符串可以完全跳过序列化,只需确保在共享之前惰性计算哈希值,因为这是唯一可变的部分,例如:

WTF::String toCrossThreadShareable(WTF::String& string)
{
    auto* impl = string.impl();
    // 不能共享原子字符串,symbol和substring字符串
    if (impl->isAtom() || impl->isSymbol() ||
        impl->bufferOwnership() == StringImpl::BufferSubstring)
        return string.isolatedCopy();
    // 在共享之前计算hash
    impl->hash();
    // Prevent this thread from atomizing.
    impl->setNeverAtomicize();
    return string;  
    // 直接共享指针
}

快速路径条件

优化适用于以下情况:

  • 使用 postMessage 或 StructuredClone
  • 仅发送字符串而非混合数据
  • 非子字符串、Row、Atom 或 Symbol
  • 向同一进程中的另一个线程发送数据
  • string.length >= 256 个字符

以上场景涵盖了在 Worker 之间发送字符串的极其常见的模式,这也是性能提升如此显著的原因。

参考资料

https://bun.com/blog/how-we-made-postMessage-string-500x-faster

https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/structuredClone

相关推荐

如何设计一个优秀的电子商务产品详情页

加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...

怎么在JS中使用Ajax进行异步请求?

大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...

中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革

前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...

前端监控 SDK 开发分享_前端监控系统 开源

一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...

Ajax 会被 fetch 取代吗?Axios 怎么办?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...

前端面试题《AJAX》_前端面试ajax考点汇总

1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...

Ajax 详细介绍_ajax

1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...

6款可替代dreamweaver的工具_替代powerdesigner的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

福斯《死侍》发布新剧照 &quot;小贱贱&quot;韦德被改造前造型曝光

时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...

不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!

Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...

2025 年 Python 爬虫四大前沿技术:从异步到 AI

作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...

最贱超级英雄《死侍》来了!_死侍超燃

死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...

停止javascript的ajax请求,取消axios请求,取消reactfetch请求

一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...