文档性能JS/WASM 基准测试

JS/WASM 基准测试

这些基准测试的主要作用是提示是否存在性能隐患,而不是用来判定哪一个项目更优秀。不同项目始终会做出不同的取舍。仅因为项目 A 在某些基准中表现更好就断言它优于项目 B 并不准确,因为项目 B 很可能在其他方面有着显著优势。

可以通过 crdt-benchmarks 仓库复现这些测试。

  • 基准测试在 MacBook Pro M1 2020(16GB RAM)上执行。
  • loro-old 指 2023-11-10 的 loro 版本,编译自 这个提交。 从那以后 Loro 做了大量改动,尤其是 编码方案。 为了在 1.0 之后保持良好的前后向兼容性,我们改用了更易扩展的编码方式。 它确实比 loro-old 使用的编码更慢,但能在不破坏兼容性的前提下更快迭代。
  • 文末还有一个更全面的基准组,仅针对 Yjs。
  • 如果所有变更都在一次 change 事务中提交,Automerge 可以在约 1 秒内完成 B4 基准(见 time 字段)。 但为了更贴近真实用户行为,我们的测试会模拟逐条编辑,并让每次编辑都生成独立的更新事件。
  • 当初始文档非空时(例如同步远端内容),automergeloroparseTime 会明显更高。
  • Loro 和 Automerge 可以为每次按键保存完整的编辑历史 DAG; 而 Yjs 若要为每个版本保存状态则需要额外存储版本向量与删除集合,这会带来超出文中统计的额外开销。
基准设置

B1:无冲突

模拟两个客户端。一方修改文本对象并将更新消息发送给另一方。我们统计执行任务的耗时(time)、通信数据量(avgUpdateSize)、任务结束后文档的编码大小(docSize)、解析编码文档的时间(parseTime),以及持有解码文档所需的内存(memUsed)。

B2:两个用户产生冲突

模拟两个客户端。双方从包含 100 个字符的同步文本对象开始,各自在单次事务中完成修改,再将变更发送给对端。我们统计将冲突变更合并到单个客户端的时间(time)、更新消息大小(updateSize)、任务结束后文档的编码大小(docSize)、解析编码文档的时间(parseTime),以及持有解码文档所需的内存(memUsed)。

B3:大量冲突

模拟 √N 个并发操作。我们统计执行任务并同步所有客户端的时间(time)、更新消息大小(updateSize)、任务结束后文档的编码大小(docSize)、解析编码文档的时间(parseTime),以及持有解码文档所需的内存(memUsed)。√N 的对数是因为 √N 个并发操作最多可能产生 √N^2 - 1 个冲突(执行操作 1:0 个冲突;执行操作 2:1 个冲突;执行操作 3:2 个冲突……)。

B4:真实编辑数据集

重放真实世界的编辑数据集。该数据集记录了一份大型文本的逐字符编辑历史,原始 LaTeX 文档见:https://arxiv.org/abs/1608.03960

来源:https://github.com/automerge/automerge-perf/tree/master/edit-by-index

  • 182,315 次单字符插入
  • 77,463 次单字符删除
  • 共 259,778 次操作
  • 最终文档包含 104,852 个字符

我们模拟单个客户端重放全部变更并保存每次更新。统计指标包括重放全部变更的耗时以及所有更新消息的大小(updateSize)、任务结束后文档的编码大小(docSize)、编码文档所需时间(encodeTime)、解析编码文档的时间(parseTime),以及文档解码后常驻内存的占用(memUsed)。

[B4 × 100] 将真实编辑数据集重放 100 次

将 [B4] 数据集重放一百遍,最终文档超过一千万个字符。作为对比,《权力的游戏:冰与火之歌》全书(含空白)也只有约 160 万字符。

  • 18,231,500 次单字符插入
  • 7,746,300 次单字符删除
  • 共 25,977,800 次操作
  • 最终文档包含 10,485,200 个字符

下表保留了基准脚本输出时的英文任务名称,便于与原始数据对照。

N = 6000yjsywasmloroloro-oldautomergeautomerge-wasm
版本13.6.150.17.41.0.0-beta.20.15.22.1.100.9.0
包体积84,017 bytes938,991 bytes2,919,363 bytes1,583,094 bytes1,696,176 bytes1,701,136 bytes
包体积(gzip)25,105 bytes284,616 bytes894,460 bytes592,039 bytes591,049 bytes594,071 bytes
[B1.1] Append N characters (time)141 ms171 ms164 ms115 ms279 ms110 ms
[B1.1] Append N characters (avgUpdateSize)27 bytes27 bytes88 bytes58 bytes121 bytes121 bytes
[B1.1] Append N characters (encodeTime)1 ms0 ms3 ms0 ms5 ms6 ms
[B1.1] Append N characters (docSize)6,031 bytes6,031 bytes12,382 bytes6,219 bytes3,992 bytes3,992 bytes
[B1.1] Append N characters (memUsed)0 B0 B0 B0 B0 B0 B
[B1.1] Append N characters (parseTime)22 ms65 ms28 ms28 ms59 ms61 ms
[B1.2] Insert string of length N (time)1 ms1 ms0 ms0 ms18 ms14 ms
[B1.2] Insert string of length N (avgUpdateSize)6,031 bytes6,031 bytes6,089 bytes6,088 bytes6,201 bytes6,201 bytes
[B1.2] Insert string of length N (encodeTime)0 ms0 ms0 ms0 ms2 ms2 ms
[B1.2] Insert string of length N (docSize)6,031 bytes6,031 bytes12,313 bytes6,146 bytes3,974 bytes3,974 bytes
[B1.2] Insert string of length N (parseTime)27 ms47 ms27 ms26 ms29 ms30 ms
[B1.3] Prepend N characters (time)118 ms30 ms111 ms47 ms272 ms73 ms
[B1.3] Prepend N characters (avgUpdateSize)27 bytes26 bytes87 bytes57 bytes116 bytes116 bytes
[B1.3] Prepend N characters (encodeTime)2 ms0 ms2 ms1 ms4 ms4 ms
[B1.3] Prepend N characters (docSize)6,041 bytes6,040 bytes15,414 bytes6,165 bytes3,988 bytes3,988 bytes
[B1.3] Prepend N characters (parseTime)45 ms38 ms27 ms37 ms73 ms47 ms
[B1.4] Insert N characters at random positions (time)128 ms101 ms113 ms51 ms268 ms89 ms
[B1.4] Insert N characters at random positions (avgUpdateSize)29 bytes29 bytes88 bytes58 bytes121 bytes121 bytes
[B1.4] Insert N characters at random positions (encodeTime)3 ms0 ms2 ms1 ms6 ms5 ms
[B1.4] Insert N characters at random positions (docSize)29,571 bytes29,554 bytes39,040 bytes29,503 bytes24,743 bytes24,743 bytes
[B1.4] Insert N characters at random positions (parseTime)46 ms30 ms27 ms26 ms73 ms64 ms
[B1.5] Insert N words at random positions (time)149 ms264 ms112 ms54 ms539 ms291 ms
[B1.5] Insert N words at random positions (avgUpdateSize)36 bytes36 bytes95 bytes65 bytes131 bytes131 bytes
[B1.5] Insert N words at random positions (encodeTime)6 ms1 ms3 ms1 ms14 ms15 ms
[B1.5] Insert N words at random positions (docSize)87,868 bytes87,924 bytes135,713 bytes98,901 bytes96,203 bytes96,203 bytes
[B1.5] Insert N words at random positions (parseTime)50 ms33 ms27 ms33 ms101 ms111 ms
[B1.6] Insert string, then delete it (time)1 ms0 ms2 ms1 ms39 ms31 ms
[B1.6] Insert string, then delete it (avgUpdateSize)6,053 bytes6,052 bytes6,189 bytes6,179 bytes6,338 bytes6,338 bytes
[B1.6] Insert string, then delete it (encodeTime)0 ms0 ms0 ms0 ms3 ms2 ms
[B1.6] Insert string, then delete it (docSize)6,040 bytes6,039 bytes6,409 bytes6,145 bytes3,993 bytes3,993 bytes
[B1.6] Insert string, then delete it (parseTime)29 ms29 ms26 ms28 ms52 ms44 ms
[B1.7] Insert/Delete strings at random positions (time)153 ms112 ms136 ms60 ms423 ms212 ms
[B1.7] Insert/Delete strings at random positions (avgUpdateSize)31 bytes31 bytes100 bytes61 bytes135 bytes135 bytes
[B1.7] Insert/Delete strings at random positions (encodeTime)3 ms1 ms3 ms1 ms13 ms11 ms
[B1.7] Insert/Delete strings at random positions (docSize)41,917 bytes41,592 bytes81,700 bytes51,470 bytes59,281 bytes59,281 bytes
[B1.7] Insert/Delete strings at random positions (parseTime)53 ms41 ms25 ms27 ms80 ms78 ms
[B1.8] Append N numbers (time)140 ms59 ms155 ms73 ms448 ms113 ms
[B1.8] Append N numbers (avgUpdateSize)32 bytes32 bytes94 bytes62 bytes125 bytes125 bytes
[B1.8] Append N numbers (encodeTime)2 ms0 ms2 ms2 ms6 ms6 ms
[B1.8] Append N numbers (docSize)35,641 bytes35,634 bytes71,568 bytes47,625 bytes26,985 bytes26,985 bytes
[B1.8] Append N numbers (parseTime)32 ms43 ms31 ms29 ms76 ms67 ms
[B1.9] Insert Array of N numbers (time)3 ms3 ms13 ms9 ms47 ms22 ms
[B1.9] Insert Array of N numbers (avgUpdateSize)35,653 bytes35,657 bytes35,715 bytes35,717 bytes31,199 bytes31,199 bytes
[B1.9] Insert Array of N numbers (encodeTime)1 ms0 ms2 ms1 ms4 ms2 ms
[B1.9] Insert Array of N numbers (docSize)35,653 bytes35,657 bytes71,578 bytes47,646 bytes26,953 bytes26,953 bytes
[B1.9] Insert Array of N numbers (parseTime)43 ms29 ms31 ms29 ms56 ms44 ms
[B1.10] Prepend N numbers (time)157 ms31 ms125 ms53 ms484 ms159 ms
[B1.10] Prepend N numbers (avgUpdateSize)32 bytes32 bytes93 bytes61 bytes120 bytes120 bytes
[B1.10] Prepend N numbers (encodeTime)3 ms1 ms3 ms1 ms6 ms6 ms
[B1.10] Prepend N numbers (docSize)35,669 bytes35,665 bytes76,773 bytes47,645 bytes26,987 bytes26,987 bytes
[B1.10] Prepend N numbers (parseTime)53 ms33 ms48 ms39 ms65 ms67 ms
[B1.11] Insert N numbers at random positions (time)160 ms121 ms125 ms56 ms517 ms121 ms
[B1.11] Insert N numbers at random positions (avgUpdateSize)34 bytes34 bytes94 bytes60 bytes125 bytes125 bytes
[B1.11] Insert N numbers at random positions (encodeTime)2 ms1 ms4 ms1 ms8 ms6 ms
[B1.11] Insert N numbers at random positions (docSize)59,132 bytes59,137 bytes100,632 bytes70,901 bytes47,746 bytes47,746 bytes
[B1.11] Insert N numbers at random positions (parseTime)52 ms50 ms58 ms41 ms428 ms80 ms
[B2.1] Concurrently insert string of length N at index 0 (time)1 ms0 ms1 ms0 ms75 ms32 ms
[B2.1] Concurrently insert string of length N at index 0 (updateSize)6,094 bytes6,094 bytes6,188 bytes9,244 bytes9,499 bytes9,499 bytes
[B2.1] Concurrently insert string of length N at index 0 (encodeTime)0 ms0 ms0 ms0 ms7 ms5 ms
[B2.1] Concurrently insert string of length N at index 0 (docSize)12,151 bytes12,151 bytes24,735 bytes12,281 bytes8,011 bytes8,011 bytes
[B2.1] Concurrently insert string of length N at index 0 (parseTime)28 ms34 ms30 ms27 ms60 ms48 ms
[B2.2] Concurrently insert N characters at random positions (time)46 ms166 ms55 ms125 ms270 ms399 ms
[B2.2] Concurrently insert N characters at random positions (updateSize)33,420 bytes33,444 bytes23,779 bytes350,337 bytes27,476 bytes1,093,293 bytes
[B2.2] Concurrently insert N characters at random positions (encodeTime)2 ms1 ms4 ms1 ms6 ms11 ms
[B2.2] Concurrently insert N characters at random positions (docSize)66,808 bytes66,852 bytes79,937 bytes59,358 bytes50,686 bytes50,704 bytes
[B2.2] Concurrently insert N characters at random positions (parseTime)67 ms69 ms27 ms27 ms51 ms95 ms
[B2.3] Concurrently insert N words at random positions (time)105 ms459 ms68 ms120 ms435 ms630 ms
[B2.3] Concurrently insert N words at random positions (updateSize)89,143 bytes88,994 bytes62,640 bytes408,723 bytes122,485 bytes1,185,202 bytes
[B2.3] Concurrently insert N words at random positions (encodeTime)7 ms2 ms7 ms3 ms28 ms35 ms
[B2.3] Concurrently insert N words at random positions (docSize)178,428 bytes178,130 bytes268,884 bytes197,284 bytes185,019 bytes191,498 bytes
[B2.3] Concurrently insert N words at random positions (parseTime)82 ms67 ms31 ms30 ms134 ms184 ms
[B2.4] Concurrently insert & delete (time)145 ms1,243 ms118 ms282 ms653 ms1,311 ms
[B2.4] Concurrently insert & delete (updateSize)140,984 bytes141,122 bytes123,725 bytes798,123 bytes298,810 bytes2,395,876 bytes
[B2.4] Concurrently insert & delete (encodeTime)6 ms3 ms14 ms4 ms43 ms56 ms
[B2.4] Concurrently insert & delete (docSize)282,112 bytes282,358 bytes392,151 bytes304,592 bytes293,831 bytes307,291 bytes
[B2.4] Concurrently insert & delete (parseTime)105 ms73 ms34 ms31 ms185 ms269 ms
[B3.1] 20√N clients concurrently set number in Map (time)54 ms60 ms27 ms32 ms1,058 ms21 ms
[B3.1] 20√N clients concurrently set number in Map (updateSize)49,167 bytes49,162 bytes132,376 bytes63,832 bytes283,296 bytes283,296 bytes
[B3.1] 20√N clients concurrently set number in Map (encodeTime)3 ms1 ms16 ms1 ms9 ms12 ms
[B3.1] 20√N clients concurrently set number in Map (docSize)36,763 bytes36,751 bytes78,764 bytes38,428 bytes86,165 bytes86,164 bytes
[B3.1] 20√N clients concurrently set number in Map (parseTime)57 ms67 ms83 ms49 ms59 ms54 ms
[B3.2] 20√N clients concurrently set Object in Map (time)55 ms62 ms27 ms40 ms1,126 ms28 ms
[B3.2] 20√N clients concurrently set Object in Map (updateSize)85,084 bytes85,073 bytes171,370 bytes99,753 bytes398,090 bytes325,370 bytes
[B3.2] 20√N clients concurrently set Object in Map (encodeTime)2 ms1 ms18 ms2 ms21 ms17 ms
[B3.2] 20√N clients concurrently set Object in Map (docSize)72,682 bytes72,659 bytes84,255 bytes75,227 bytes112,588 bytes93,401 bytes
[B3.2] 20√N clients concurrently set Object in Map (parseTime)73 ms68 ms83 ms48 ms68 ms59 ms
[B3.3] 20√N clients concurrently set String in Map (time)124 ms61 ms63 ms73 ms1,869 ms166 ms
[B3.3] 20√N clients concurrently set String in Map (updateSize)7,826,229 bytes7,826,225 bytes7,912,520 bytes7,840,917 bytes8,063,440 bytes8,063,440 bytes
[B3.3] 20√N clients concurrently set String in Map (encodeTime)56 ms5 ms70 ms23 ms59 ms61 ms
[B3.3] 20√N clients concurrently set String in Map (docSize)7,813,826 bytes7,813,814 bytes241,646 bytes7,815,537 bytes97,997 bytes98,008 bytes
[B3.3] 20√N clients concurrently set String in Map (parseTime)141 ms75 ms161 ms44 ms80 ms76 ms
[B3.4] 20√N clients concurrently insert text in Array (time)45 ms49 ms195 ms28 ms1,768 ms19 ms
[B3.4] 20√N clients concurrently insert text in Array (updateSize)52,751 bytes52,735 bytes137,490 bytes70,514 bytes311,830 bytes285,330 bytes
[B3.4] 20√N clients concurrently insert text in Array (encodeTime)1 ms0 ms13 ms1 ms13 ms7 ms
[B3.4] 20√N clients concurrently insert text in Array (docSize)26,596 bytes26,580 bytes100,791 bytes47,943 bytes96,423 bytes86,519 bytes
[B3.4] 20√N clients concurrently insert text in Array (parseTime)55 ms37 ms94 ms30 ms43 ms37 ms
[B4] Apply real-world editing dataset (time)2,616 ms17,556 ms2,271 ms768 ms7,109 ms2,775 ms
[B4] Apply real-world editing dataset (encodeTime)4 ms8 ms11 ms3 ms165 ms161 ms
[B4] Apply real-world editing dataset (docSize)226,981 bytes226,981 bytes230,556 bytes260,813 bytes129,116 bytes129,116 bytes
[B4] Apply real-world editing dataset (parseTime)27 ms22 ms6 ms4 ms1,185 ms1,123 ms
[B4x100] Apply real-world editing dataset 100 times (time)279,705 msskipped233,739 ms75,122 msskippedskipped
[B4x100] Apply real-world editing dataset 100 times (encodeTime)417 msskipped743 ms205 msskippedskipped
[B4x100] Apply real-world editing dataset 100 times (docSize)22,694,543 bytesskipped21,016,454 bytes26,826,427 bytesskippedskipped
[B4x100] Apply real-world editing dataset 100 times (parseTime)1,270 msskipped66 ms200 msskippedskipped
[B3.5] 20√N clients concurrently insert text (time)42 ms49 ms212 ms115 ms1,869 ms36 ms
[B3.5] 20√N clients concurrently insert text (updateSize)48,129 bytes48,135 bytes132,870 bytes68,978 bytes298,020 bytes298,020 bytes
[B3.5] 20√N clients concurrently insert text (encodeTime)1 ms0 ms13 ms1 ms12 ms16 ms
[B3.5] 20√N clients concurrently insert text (docSize)24,313 bytes24,325 bytes102,818 bytes48,053 bytes90,768 bytes90,781 bytes
[B3.5] 20√N clients concurrently insert text (parseTime)38 ms38 ms64 ms63 ms67 ms55 ms
[C1.1] Concurrently insert & delete 100K (time)27,138 msskipped2,335 msskipped50,692 msskipped
[C1.1] Concurrently insert & delete 100K (updateSize)4,908,122 bytesskipped4,269,521 bytesskipped10,326,487 bytesskipped
[C1.1] Concurrently insert & delete 100K (encodeTime)129 msskipped210 msskipped837 msskipped
[C1.1] Concurrently insert & delete 100K (docSize)4,908,186 bytesskipped6,748,052 bytesskipped5,404,289 bytesskipped
[C1.1] Concurrently insert & delete 100K (parseTime)1,653 msskipped78 msskipped7,308 msskipped
[C1.1] Concurrently insert & delete 100K (versionSize)222,681 bytesskipped28 bytesskipped64 bytesskipped
[C1.2] Concurrently set Map 100K (time)31,598 msskipped488 msskipped472,547 msskipped
[C1.2] Concurrently set Map 100K (updateSize)980,804 bytesskipped2,601,744 bytesskipped5,541,744 bytesskipped
[C1.2] Concurrently set Map 100K (encodeTime)60 msskipped203 msskipped2,652 msskipped
[C1.2] Concurrently set Map 100K (docSize)738,949 bytesskipped1,539,209 bytesskipped1,743,081 bytesskipped
[C1.2] Concurrently set Map 100K (parseTime)4,069 msskipped631 msskipped338 msskipped
[C1.2] Concurrently set Map 100K (versionSize)416,246 bytesskipped314,810 bytesskipped1,949,999 bytesskipped