Docs
Performance
JS/WASM Benchmarks

JS/WASM Benchmarks

The benchmark is based on crdt-benchmarks (opens in a new tab) repo.

  • The memUsed result has been removed from the current benchmark because it is not reported correctly when using WASM.
  • During the benchmark, loro-wasm was configured not to use compression on the doc, and it preserves the entire editing history, resulting in a larger docSize.

On 2023-11-08, the benchmark test was performed on a 13-inch M1 MacBook Pro 2020. The benchmark uses the most recent versions of loro-wasm, ywasm, and yjs available on that date. However, an older version of automerge-wasm (v0.1.2, published in 2022) was used.

NOTE: The current benchmark is somewhat outdated, particularly after numerous refactorings, which have altered performance characteristics. We plan to update this document shortly.

Benchmark setup

B1: No conflicts

Simulate two clients. One client modifies a text object and sends update messages to the other client. We measure the time to perform the task (time), the amount of data exchanged (avgUpdateSize), the size of the encoded document after the task is performed (docSize), the time to parse the encoded document (parseTime), and the memory used to hold the decoded document (memUsed).

B2: Two users producing conflicts

Simulate two clients. Both start with a synced text object containing 100 characters. Both clients modify the text object in a single transaction and then send their changes to the other client. We measure the time to sync concurrent changes into a single client (time), the size of the update messages (updateSize), the size of the encoded document after the task is performed (docSize), the time to parse the encoded document (parseTime), and the memory used to hold the decoded document (memUsed).

B3: Many conflicts

Simulate √N concurrent actions. We measure the time to perform the task and sync all clients (time), the size of the update messages (updateSize), the size of the encoded document after the task is performed (docSize), the time to parse the encoded document (parseTime), and the memory used to hold the decoded document (memUsed). The logarithm of N was chosen because √N concurrent actions may result in up to √N^2 - 1 conflicts (apply action 1: 0 conlict; apply action2: 1 conflict, apply action 2: 2 conflicts, ..).

B4: Real-world editing dataset

Replay a real-world editing dataset. This dataset contains the character-by-character editing trace of a large-ish text document, the LaTeX source of this paper: https://arxiv.org/abs/1608.03960 (opens in a new tab)

Source: https://github.com/automerge/automerge-perf/tree/master/edit-by-index (opens in a new tab)

  • 182,315 single-character insertion operations
  • 77,463 single-character deletion operations
  • 259,778 operations totally
  • 104,852 characters in the final document

We simulate one client replaying all changes and storing each update. We measure the time to replay the changes and the size of all update messages (updateSize), the size of the encoded document after the task is performed (docSize), the time to encode the document (encodeTime), the time to parse the encoded document (parseTime), and the memory used to hold the decoded document in memory (memUsed).

[B4 x 100] Real-world editing dataset 100 times

Replay the [B4] dataset one hundred times. The final document has a size of over 10 million characters. As comparison, the book "Game of Thrones: A Song of Ice and Fire" is only 1.6 million characters long (including whitespace).

  • 18,231,500 single-character insertion operations
  • 7,746,300 single-character deletion operations
  • 25,977,800 operations totally
  • 10,485,200 characters in the final document
N = 6000loro-wasmyjsautomerge-wasmywasm
[B1.1] Append N characters (time)54 ms86 ms61 ms72 ms
[B1.1] Append N characters (avgUpdateSize)58 bytes27 bytes121 bytes27 bytes
[B1.1] Append N characters (encodeTime)0 ms1 ms7 ms0 ms
[B1.1] Append N characters (docSize)6219 bytes6031 bytes3995 bytes6031 bytes
[B1.1] Append N characters (parseTime)0 ms0 ms38 ms0 ms
[B1.2] Insert string of length N (time)0 ms1 ms28 ms0 ms
[B1.2] Insert string of length N (avgUpdateSize)6096 bytes6031 bytes6201 bytes6031 bytes
[B1.2] Insert string of length N (encodeTime)0 ms2 ms2 ms0 ms
[B1.2] Insert string of length N (docSize)6148 bytes6031 bytes3977 bytes6031 bytes
[B1.2] Insert string of length N (parseTime)0 ms0 ms12 ms0 ms
[B1.3] Prepend N characters (time)23 ms73 ms45 ms16 ms
[B1.3] Prepend N characters (avgUpdateSize)57 bytes27 bytes116 bytes27 bytes
[B1.3] Prepend N characters (encodeTime)1 ms2 ms8 ms0 ms
[B1.3] Prepend N characters (docSize)6165 bytes6041 bytes3991 bytes6041 bytes
[B1.3] Prepend N characters (parseTime)1 ms5 ms34 ms1 ms
[B1.4] Insert N characters at random positions (time)19 ms68 ms214 ms80 ms
[B1.4] Insert N characters at random positions (avgUpdateSize)58 bytes29 bytes121 bytes29 bytes
[B1.4] Insert N characters at random positions (encodeTime)1 ms2 ms8 ms0 ms
[B1.4] Insert N characters at random positions (docSize)29503 bytes29554 bytes24746 bytes29554 bytes
[B1.4] Insert N characters at random positions (parseTime)1 ms3 ms64 ms3 ms
[B1.5] Insert N words at random positions (time)20 ms71 ms986 ms245 ms
[B1.5] Insert N words at random positions (avgUpdateSize)63 bytes36 bytes131 bytes36 bytes
[B1.5] Insert N words at random positions (encodeTime)2 ms3 ms23 ms1 ms
[B1.5] Insert N words at random positions (docSize)98899 bytes87924 bytes96206 bytes87924 bytes
[B1.5] Insert N words at random positions (parseTime)2 ms8 ms144 ms5 ms
[B1.6] Insert string, then delete it (time)0 ms5 ms36 ms0 ms
[B1.6] Insert string, then delete it (avgUpdateSize)6191 bytes6053 bytes6338 bytes6053 bytes
[B1.6] Insert string, then delete it (encodeTime)0 ms0 ms4 ms0 ms
[B1.6] Insert string, then delete it (docSize)6143 bytes38 bytes3996 bytes38 bytes
[B1.6] Insert string, then delete it (parseTime)0 ms0 ms28 ms0 ms
[B1.7] Insert/Delete strings at random positions (time)28 ms85 ms763 ms74 ms
[B1.7] Insert/Delete strings at random positions (avgUpdateSize)61 bytes31 bytes135 bytes31 bytes
[B1.7] Insert/Delete strings at random positions (encodeTime)1 ms7 ms18 ms0 ms
[B1.7] Insert/Delete strings at random positions (docSize)51470 bytes28377 bytes59284 bytes28377 bytes
[B1.7] Insert/Delete strings at random positions (parseTime)1 ms10 ms112 ms2 ms
[B1.8] Append N numbers (time)23 ms85 ms146 ms16 ms
[B1.8] Append N numbers (avgUpdateSize)60 bytes32 bytes125 bytes32 bytes
[B1.8] Append N numbers (encodeTime)2 ms1 ms10 ms0 ms
[B1.8] Append N numbers (docSize)47623 bytes35634 bytes26988 bytes35634 bytes
[B1.8] Append N numbers (parseTime)3 ms0 ms68 ms0 ms
[B1.9] Insert Array of N numbers (time)5 ms1 ms24 ms2 ms
[B1.9] Insert Array of N numbers (avgUpdateSize)35725 bytes35657 bytes31199 bytes35657 bytes
[B1.9] Insert Array of N numbers (encodeTime)1 ms1 ms2 ms0 ms
[B1.9] Insert Array of N numbers (docSize)47648 bytes35657 bytes26956 bytes35657 bytes
[B1.9] Insert Array of N numbers (parseTime)3 ms0 ms23 ms0 ms
[B1.10] Prepend N numbers (time)16 ms51 ms382 ms15 ms
[B1.10] Prepend N numbers (avgUpdateSize)59 bytes32 bytes120 bytes32 bytes
[B1.10] Prepend N numbers (encodeTime)1 ms1 ms10 ms0 ms
[B1.10] Prepend N numbers (docSize)47643 bytes35665 bytes26990 bytes35665 bytes
[B1.10] Prepend N numbers (parseTime)3 ms1 ms51 ms2 ms
[B1.11] Insert N numbers at random positions (time)16 ms58 ms458 ms113 ms
[B1.11] Insert N numbers at random positions (avgUpdateSize)62 bytes34 bytes125 bytes34 bytes
[B1.11] Insert N numbers at random positions (encodeTime)1 ms2 ms12 ms0 ms
[B1.11] Insert N numbers at random positions (docSize)70903 bytes59137 bytes47749 bytes59137 bytes
[B1.11] Insert N numbers at random positions (parseTime)3 ms3 ms70 ms3 ms
[B2.1] Concurrently insert string of length N at index 0 (time)0 ms0 ms104 ms0 ms
[B2.1] Concurrently insert string of length N at index 0 (updateSize)9256 bytes6094 bytes9499 bytes6093 bytes
[B2.1] Concurrently insert string of length N at index 0 (encodeTime)0 ms0 ms4 ms0 ms
[B2.1] Concurrently insert string of length N at index 0 (docSize)12282 bytes12152 bytes8014 bytes12150 bytes
[B2.1] Concurrently insert string of length N at index 0 (parseTime)0 ms0 ms43 ms0 ms
[B2.2] Concurrently insert N characters at random positions (time)117 ms25 ms1496 ms210 ms
[B2.2] Concurrently insert N characters at random positions (updateSize)344345 bytes33444 bytes1093293 bytes177007 bytes
[B2.2] Concurrently insert N characters at random positions (encodeTime)1 ms2 ms18 ms1 ms
[B2.2] Concurrently insert N characters at random positions (docSize)59356 bytes66860 bytes50708 bytes66852 bytes
[B2.2] Concurrently insert N characters at random positions (parseTime)2 ms15 ms142 ms6 ms
[B2.3] Concurrently insert N words at random positions (time)144 ms55 ms2915 ms569 ms
[B2.3] Concurrently insert N words at random positions (updateSize)408728 bytes88994 bytes1185202 bytes215213 bytes
[B2.3] Concurrently insert N words at random positions (encodeTime)3 ms4 ms48 ms4 ms
[B2.3] Concurrently insert N words at random positions (docSize)197284 bytes178130 bytes191500 bytes178130 bytes
[B2.3] Concurrently insert N words at random positions (parseTime)3 ms13 ms311 ms11 ms
[B2.4] Concurrently insert & delete (time)259 ms95 ms5682 ms1500 ms
[B2.4] Concurrently insert & delete (updateSize)786130 bytes139517 bytes2395876 bytes398881 bytes
[B2.4] Concurrently insert & delete (encodeTime)4 ms6 ms87 ms5 ms
[B2.4] Concurrently insert & delete (docSize)304590 bytes279166 bytes307364 bytes279172 bytes
[B2.4] Concurrently insert & delete (parseTime)4 ms27 ms444 ms32 ms
[B3.1] 20√N clients concurrently set number in Map (time)23 ms52 ms35 ms156 ms
[B3.1] 20√N clients concurrently set number in Map (updateSize)63850 bytes49163 bytes283296 bytes49172 bytes
[B3.1] 20√N clients concurrently set number in Map (encodeTime)2 ms2 ms13 ms1 ms
[B3.1] 20√N clients concurrently set number in Map (docSize)38464 bytes32212 bytes83205 bytes32214 bytes
[B3.1] 20√N clients concurrently set number in Map (parseTime)22 ms14 ms38 ms10 ms
[B3.2] 20√N clients concurrently set Object in Map (time)40 ms50 ms42 ms156 ms
[B3.2] 20√N clients concurrently set Object in Map (updateSize)99763 bytes85077 bytes325370 bytes85083 bytes
[B3.2] 20√N clients concurrently set Object in Map (encodeTime)3 ms2 ms20 ms1 ms
[B3.2] 20√N clients concurrently set Object in Map (docSize)74377 bytes32223 bytes90426 bytes32240 bytes
[B3.2] 20√N clients concurrently set Object in Map (parseTime)24 ms13 ms34 ms11 ms
[B3.3] 20√N clients concurrently set String in Map (time)100 ms70 ms215 ms167 ms
[B3.3] 20√N clients concurrently set String in Map (updateSize)7840873 bytes7826231 bytes8063440 bytes7826231 bytes
[B3.3] 20√N clients concurrently set String in Map (encodeTime)28 ms2 ms52 ms2 ms
[B3.3] 20√N clients concurrently set String in Map (docSize)7815449 bytes38369 bytes95086 bytes36840 bytes
[B3.3] 20√N clients concurrently set String in Map (parseTime)7 ms13 ms74 ms14 ms
[B3.4] 20√N clients concurrently insert text in Array (time)28 ms44 ms33 ms165 ms
[B3.4] 20√N clients concurrently insert text in Array (updateSize)70476 bytes52745 bytes285330 bytes52737 bytes
[B3.4] 20√N clients concurrently insert text in Array (encodeTime)1 ms2 ms19 ms1 ms
[B3.4] 20√N clients concurrently insert text in Array (docSize)47868 bytes26590 bytes83577 bytes26582 bytes
[B3.4] 20√N clients concurrently insert text in Array (parseTime)5 ms2 ms41 ms4 ms
[B4] Apply real-world editing dataset (time)158 ms1028 ms1542 ms23006 ms
[B4] Apply real-world editing dataset (avgUpdateSize)skipped29 bytesskippedskipped
[B4] Apply real-world editing dataset (encodeTime)2 ms4 ms131 ms3 ms
[B4] Apply real-world editing dataset (docSize)260815 bytes159929 bytes129098 bytes159929 bytes
[B4] Apply real-world editing dataset (parseTime)2 ms6 ms615 ms14 ms
[B4x100] Apply real-world editing dataset 100 times (time)15251 ms110404 msskippedskipped
[B4x100] Apply real-world editing dataset 100 times (encodeTime)222 ms266 msskippedskipped
[B4x100] Apply real-world editing dataset 100 times (docSize)26826425 bytes15989245 bytesskippedskipped
[B4x100] Apply real-world editing dataset 100 times (parseTime)180 ms1357 msskippedskipped