【问题标题】:Fastest possible Javascript object serialization with Google V8使用 Google V8 实现最快的 Javascript 对象序列化
【发布时间】:2011-09-07 07:01:20
【问题描述】:

我需要序列化具有 1-100 个混合类型属性的中等复杂对象。

最初使用 JSON,然后我切换到 BSON,它稍微快了一点。

编码 10000 个样本对象

JSON:        1807mS
BSON:        1687mS
MessagePack: 2644mS (JS, modified for BinaryF)

我想要一个数量级的增长;它对系统的其余部分产生了非常糟糕的影响。

迁移到 BSON 的部分动机是需要对二进制数据进行编码,因此 JSON(现在)不适合。而且因为它只是跳过了对象中存在的二进制数据,所以它在那些基准测试中“作弊”。

剖析的 BSON 性能热点

  • (不可避免?)将 UTF16 V8 JS 字符串转换为 UTF8。
  • BSON 库中的 malloc 和字符串操作

BSON 编码器基于 Mongo BSON 库。

原生 V8 二进制序列化器可能很棒,但由于 JSON 是原生的并且可以快速序列化,我担心即使这样也无法提供答案。也许我最好的选择是优化 BSON 库的性能,或者编写我自己的 plus 找出更有效的方法来从 V8 中提取字符串。一种策略可能是为 BSON 添加 UTF16 支持。

所以我来这里是为了想法,也许是为了检查一下。

编辑

添加了 MessagePack 基准。这是从原始 JS 修改为使用 BinaryF。

C++ MessagePack 库可能会提供进一步的改进,我可能会单独对其进行基准测试以直接与 BSON 库进行比较。

【问题讨论】:

  • 也许您可以提供一个jsperf.com 测试用例来帮助了解您需要存储的数据类型
  • 只是标准 JS 对象:{param1:"name",param2:{paramA:1,paramB:[0x0,0x1,0x2],paramC:}} 最多 100 个属性,任意嵌套,其中一些将包含使用 CommonJS BinaryF 的字节数组。如果没有 BinaryF 和 BSON 序列化程序,就不可能进行任何有用的比较。
  • 您是否有任何链接/参考您用于 BSON、MsgPack 等的内容?
  • 这些基准在 2013 年的适用性如何? PS:长期通过window.btoa可以将二进制对象打包成JSON。
  • 我已经很久没有运行这些测试了。 AFAIK window.btoa/atob 是 base64,因此需要额外的处理(如 JSON.stringify/parse)来获取/从 base64 兼容数据,所以它会更慢。

标签: javascript serialization v8 bson embedded-v8


【解决方案1】:

看看MessagePack。它与 JSON 兼容。来自文档:

快速紧凑的序列化

MessagePack 是一个基于二进制的 高效的对象序列化 图书馆。它可以交换 许多之间的结构化对象 像 JSON 这样的语言。但与 JSON 不同的是, 它又快又小。

典型的小整数(如标志或 错误代码)仅保存在 1 个字节中, 典型的短字符串只需要 1 除字符串长度外的字节 本身。 [1,2,3](3 个元素数组)是 使用 4 个字节序列化 MessagePack如下:

【讨论】:

  • 太棒了!绝对值得测试!我先试一下 JS 的实现。
  • 现在再次测试 MessagePack vs JSON :) JSON 完全破坏了它,bson 也是如此(即使是带有 c++ 绑定的本机 bson)。是的,我知道这个问题大约有 5 年的历史了,但是伙计,JSON 现在很难被击败。不过,我确实在他们的 github 页面上为 MsgPack 提供了确认失败的道具,哈哈哈。 -- 它甚至没有接近
  • 我只是在我的一个文本示例 JSON.stringify 中比较了序列化字符串返回 MessagePack 与 JSON,生成长度为 1011 的字符串与 MessagePack 字符串长度 2231 进行比较
【解决方案2】:

对于序列化/反序列化protobuf 很难被击败。我不知道您是否可以切换传输协议。但是如果可以protobuf肯定应该考虑。

查看Protocol Buffers versus JSON or BSON 的所有答案。

接受的答案选择thrift。然而,它比 protobuf 慢。我怀疑选择它是为了易于使用(使用 Java)而不是速度。 These Java benchmarks 很有说服力。
注意

  • MongoDB-BSON 45042
  • protobuf 6539
  • protostuff/protobuf 3318

基准测试是 Java,我想您可以达到接近 protobuf 的 protostuff 实现的速度,即快 13.5 倍。最坏的情况(如果出于某种原因,Java 只是更适​​合序列化),那么运行速度快 6.8 倍的普通未优化 protobuf 实现也不会更糟。

【讨论】:

  • 感谢您的基准测试。数据是用户生成的,因此 PB 协议需要携带键/值对,这会破坏它的一些性能优势,但我预计它仍然会以很大的优势脱颖而出。虽然它不支持 UTF16,所以添加该类型应该不难。
  • 我坚持使用 BSON 并逐步优化。但我很可能会在某个时候回到 protobuf。谢谢。
【解决方案3】:

如果您对反序列化速度更感兴趣,请查看JBB (Javascript Binary Bundles) 库。它比 BSON 或 MsgPack 快。

来自 Wiki,页面 JBB vs BSON vs MsgPack

...

  • JBB 的解码速度比 Binary-JSON (BSON) 快约 70%,解码速度比 MsgPack 快约 30%,即使使用一个负测试用例 (#3) 也是如此。
  • JBB 创建的文件(甚至是压缩版本)比 Binary-JSON (BSON) 小约 61%,比 MsgPack 小约 55%。

...

很遗憾,它不是流媒体格式,这意味着您必须离线预处理数据。但是有一个将其转换为流格式的计划(检查里程碑)。

【讨论】:

    【解决方案4】:

    我最近(2020 年)article and benchmark 比较了 JavaScript 中的二进制序列化库。

    比较以下格式和库:

    • 协议缓冲区:protobuf-jspbfprotonsgoogle-protobuf
    • Avro:avsc
    • BSON:bson
    • BSER:bser
    • JSBinary:js-binary

    根据当前的基准测试结果,我将按以下顺序对顶级库进行排名(值越高越好,测量值比 JSON 快 x 倍):

    1. avsc:10x 编码,3-10x 解码
    2. js-binary:2x 编码,2-8x 解码
    3. protobuf-js:0.5-1x 编码,2-6x 解码,
    4. pbf:1.2x 编码,1.0x 解码
    5. bser:0.5x 编码,0.5x 解码
    6. bson:0.5x 编码,0.7x 解码

    我没有在基准测试中包含msgpack,因为根据其 NPM 描述,它目前比内置 JSON 库慢。

    详情见article全文。

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      相关资源
      最近更新 更多