Benchmark
JSON against jalapenojson: the same rows, read and written by each, in JavaScript, Python, C and WebAssembly. Every table has the same shape: JSON in one column, jalapenojson in the next, and how many times faster or slower jalapenojson is.
Measured on 2026-10-03 at commit 2eb975b: Intel Xeon Processor @ 2.10GHz, 4 cores, Linux 6.18.44-fc-v64; Node 24.21.0, Python 3.11.15, cc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0 with -O2, cJSON 1.7.19, yyjson 0.13.0. Reproduce with bench/run.sh.
The data
Two sets of rows with the same seven columns: id (i), user, city and plan (s), seats (i), price (f) and joined (d). They are never averaged, because they disagree about size.
- repetitive is the shape API output usually has: a user drawn from two thousand, a city from eight (one of them Tromsø, so the text is not pure ASCII), a plan from four, a price from a price list.
- high-entropy fills the same columns with random letters and numbers, so there is little for a compressor to find in either format.
- nested orders, orders carrying one to six line items each, is measured for size only.
bench/data.mjs writes each set once, as JSON and as jalapenojson, and every language reads those same files.
Size
Raw, then compressed the way a server would send it: gzip at level 6, brotli at quality 5 (compressed as it is sent) and 11 (compressed once, ahead of time).
| 50,000 rows | JSON | jalapenojson | difference |
|---|
| repetitive, raw | 5.55 MB | 2.75 MB | 50% smaller |
| repetitive, gzip | 609 KB | 533 KB | 13% smaller |
| repetitive, brotli 5 | 609 KB | 490 KB | 20% smaller |
| repetitive, brotli 11 | 460 KB | 403 KB | 12% smaller |
| high-entropy, raw | 6.27 MB | 3.50 MB | 44% smaller |
| high-entropy, gzip | 2.27 MB | 2.09 MB | 8% smaller |
| high-entropy, brotli 5 | 2.20 MB | 2.02 MB | 8% smaller |
| high-entropy, brotli 11 | 2.01 MB | 1.88 MB | 6% smaller |
| nested orders, raw | 12.04 MB | 5.22 MB | 57% smaller |
| nested orders, gzip | 1.78 MB | 1.54 MB | 14% smaller |
| nested orders, brotli 5 | 1.72 MB | 1.53 MB | 11% smaller |
| nested orders, brotli 11 | 1.39 MB | 1.25 MB | 10% smaller |
JavaScript
JSON.parse and JSON.stringify against decode(), view() and encode(), on Node 24.21.0. Warmed up: the fastest run once the reader has run for 200 ms, which is what a server or a page that reads many documents sees.
- read every value builds every row as an object:
JSON.parse against decode(). - read every value, as columns ends with one array per column:
JSON.parse and a pass per column, against view() and column(). - read one number column, read one text column and read one row end with the values of
price, of city, or of the middle row: JSON.parse and a pass, against view() and column() or row(). - write every value turns the rows each reader built back into bytes:
JSON.stringify and a TextEncoder, against encode().
| 50,000 rows | data | JSON | jalapenojson | difference |
|---|
| read every value | repetitive | 24.4 ms | 20.9 ms | 1.2x faster |
| high-entropy | 31.2 ms | 17.2 ms | 1.8x faster |
| read every value, as columns | repetitive | 32.6 ms | 17.3 ms | 1.9x faster |
| high-entropy | 39.4 ms | 14.5 ms | 2.7x faster |
| read one number column | repetitive | 25.3 ms | 1.69 ms | 15x faster |
| high-entropy | 31.7 ms | 1.63 ms | 19x faster |
| read one text column | repetitive | 26.0 ms | 4.92 ms | 5.3x faster |
| high-entropy | 33.3 ms | 2.38 ms | 14x faster |
| read one row | repetitive | 23.6 ms | 0.104 ms | 228x faster |
| high-entropy | 30.8 ms | 0.122 ms | 252x faster |
| write every value | repetitive | 22.3 ms | 15.6 ms | 1.4x faster |
| high-entropy | 22.1 ms | 26.2 ms | 1.2x slower |
JSON's time includes turning the bytes into the string JSON.parse takes, because jalapenojson's includes reading the same bytes. Handed a string it already has, JSON.parse alone takes 20.9 ms on the repetitive rows and 26.8 ms on the high-entropy rows at 50,000 rows.
The first call
A page that reads one document reads it once, in a process that has never run the reader: V8 compiles a JavaScript reader as it goes, while JSON.parse is already machine code. Each number is the median of one run in each of several fresh processes.
| 1,000 rows, first call | data | JSON | jalapenojson | difference |
|---|
| read every value | repetitive | 0.993 ms | 4.85 ms | 4.9x slower |
| high-entropy | 1.19 ms | 3.85 ms | 3.2x slower |
| read one number column | repetitive | 1.11 ms | 1.77 ms | 1.6x slower |
| high-entropy | 1.41 ms | 1.88 ms | 1.3x slower |
| read one text column | repetitive | 1.12 ms | 2.53 ms | 2.3x slower |
| high-entropy | 1.22 ms | 1.80 ms | 1.5x slower |
| read one row | repetitive | 1.04 ms | 1.34 ms | 1.3x slower |
| high-entropy | 1.12 ms | 1.35 ms | 1.2x slower |
| 50,000 rows, first call | data | JSON | jalapenojson | difference |
|---|
| read every value | repetitive | 42.9 ms | 51.4 ms | 1.2x slower |
| high-entropy | 60.5 ms | 42.3 ms | 1.4x faster |
| read one number column | repetitive | 46.1 ms | 9.75 ms | 4.7x faster |
| high-entropy | 58.3 ms | 11.2 ms | 5.2x faster |
| read one text column | repetitive | 44.4 ms | 18.7 ms | 2.4x faster |
| high-entropy | 57.5 ms | 12.4 ms | 4.6x faster |
| read one row | repetitive | 50.0 ms | 2.50 ms | 20x faster |
| high-entropy | 55.3 ms | 2.54 ms | 22x faster |
1,000 rows
| 1,000 rows | data | JSON | jalapenojson | difference |
|---|
| read every value | repetitive | 0.422 ms | 0.337 ms | 1.3x faster |
| high-entropy | 0.422 ms | 0.289 ms | 1.5x faster |
| read every value, as columns | repetitive | 0.527 ms | 0.232 ms | 2.3x faster |
| high-entropy | 0.540 ms | 0.187 ms | 2.9x faster |
| read one number column | repetitive | 0.428 ms | 0.026 ms | 17x faster |
| high-entropy | 0.423 ms | 0.030 ms | 14x faster |
| read one text column | repetitive | 0.422 ms | 0.056 ms | 7.6x faster |
| high-entropy | 0.422 ms | 0.024 ms | 17x faster |
| read one row | repetitive | 0.419 ms | 0.006 ms | 67x faster |
| high-entropy | 0.416 ms | 0.007 ms | 63x faster |
| write every value | repetitive | 0.325 ms | 0.310 ms | about the same |
| high-entropy | 0.313 ms | 0.399 ms | 1.3x slower |
In a browser
Everything above starts with the bytes in memory. A page has to receive them first. Chromium 141.0.7390.37, driven by Playwright, fetches each document from a local server that sends it gzipped, over a connection DevTools slows to a given speed and latency, and then reads it: what a page that fetches one document waits for. The download is the fastest of three; the read is the first one a fresh page does, the median of several pages.
| 50,000 rows, fast 4G (9 Mbit/s, 85 ms) | data | JSON | jalapenojson | difference |
|---|
| receive the document | repetitive | 722 ms | 577 ms | 1.3x faster |
| high-entropy | 2,139 ms | 1,971 ms | 1.1x faster |
| receive it and read every value | repetitive | 751 ms | 622 ms | 1.2x faster |
| high-entropy | 2,173 ms | 2,012 ms | 1.1x faster |
| receive it and read one number column | repetitive | 753 ms | 583 ms | 1.3x faster |
| high-entropy | 2,177 ms | 1,977 ms | 1.1x faster |
| receive it and read one row | repetitive | 753 ms | 580 ms | 1.3x faster |
| high-entropy | 2,173 ms | 1,973 ms | 1.1x faster |
| 50,000 rows, slow link (1.6 Mbit/s, 150 ms) | data | JSON | jalapenojson | difference |
|---|
| receive the document | repetitive | 3,226 ms | 2,834 ms | 1.1x faster |
| high-entropy | 11,543 ms | 10,611 ms | 1.1x faster |
| receive it and read every value | repetitive | 3,255 ms | 2,878 ms | 1.1x faster |
| high-entropy | 11,577 ms | 10,652 ms | 1.1x faster |
| receive it and read one number column | repetitive | 3,257 ms | 2,840 ms | 1.1x faster |
| high-entropy | 11,581 ms | 10,617 ms | 1.1x faster |
| receive it and read one row | repetitive | 3,256 ms | 2,836 ms | 1.1x faster |
| high-entropy | 11,577 ms | 10,613 ms | 1.1x faster |
At 50,000 rows on fast 4G, reading every value is 4% with JSON and 7% with jalapenojson on the repetitive rows, and 2% with JSON and 2% with jalapenojson on the high-entropy rows, of what the page waits for. The rest is the download.
| 1,000 rows, fast 4G (9 Mbit/s, 85 ms) | data | JSON | jalapenojson | difference |
|---|
| receive the document | repetitive | 105 ms | 102 ms | about the same |
| high-entropy | 130 ms | 126 ms | about the same |
| receive it and read every value | repetitive | 106 ms | 106 ms | about the same |
| high-entropy | 130 ms | 130 ms | about the same |
| receive it and read one number column | repetitive | 106 ms | 103 ms | about the same |
| high-entropy | 131 ms | 128 ms | about the same |
| receive it and read one row | repetitive | 106 ms | 103 ms | about the same |
| high-entropy | 130 ms | 128 ms | about the same |
| 1,000 rows, slow link (1.6 Mbit/s, 150 ms) | data | JSON | jalapenojson | difference |
|---|
| receive the document | repetitive | 217 ms | 209 ms | about the same |
| high-entropy | 382 ms | 367 ms | about the same |
| receive it and read every value | repetitive | 217 ms | 213 ms | about the same |
| high-entropy | 383 ms | 370 ms | about the same |
| receive it and read one number column | repetitive | 217 ms | 211 ms | about the same |
| high-entropy | 383 ms | 369 ms | about the same |
| receive it and read one row | repetitive | 217 ms | 210 ms | about the same |
| high-entropy | 383 ms | 368 ms | about the same |
At 1,000 rows on fast 4G, reading every value is under 1% with JSON and 4% with jalapenojson on the repetitive rows, and under 1% with JSON and 3% with jalapenojson on the high-entropy rows, of what the page waits for. The rest is the download.
Python
json.loads and json.dumps against decode(), view() and encode(), on Python 3.11.15. The same tasks, warmed up the same way. Python's json is written in C; jalapenojson's Python reader is Python. JSON is written compact and as UTF-8, the way the file it was read from was.
| 50,000 rows | data | JSON | jalapenojson | difference |
|---|
| read every value | repetitive | 56.8 ms | 50.4 ms | 1.1x faster |
| high-entropy | 54.8 ms | 57.4 ms | about the same |
| read every value, as columns | repetitive | 74.8 ms | 33.5 ms | 2.2x faster |
| high-entropy | 66.0 ms | 39.3 ms | 1.7x faster |
| read one number column | repetitive | 50.8 ms | 7.66 ms | 6.6x faster |
| high-entropy | 44.9 ms | 7.30 ms | 6.1x faster |
| read one text column | repetitive | 54.8 ms | 6.47 ms | 8.5x faster |
| high-entropy | 50.0 ms | 6.02 ms | 8.3x faster |
| read one row | repetitive | 59.0 ms | 0.099 ms | 596x faster |
| high-entropy | 52.6 ms | 0.124 ms | 425x faster |
| write every value | repetitive | 81.2 ms | 57.9 ms | 1.4x faster |
| high-entropy | 86.0 ms | 64.4 ms | 1.3x faster |
1,000 rows
| 1,000 rows | data | JSON | jalapenojson | difference |
|---|
| read every value | repetitive | 0.855 ms | 0.789 ms | 1.1x faster |
| high-entropy | 0.752 ms | 0.863 ms | 1.1x slower |
| read every value, as columns | repetitive | 1.00 ms | 0.572 ms | 1.7x faster |
| high-entropy | 0.918 ms | 0.645 ms | 1.4x faster |
| read one number column | repetitive | 0.889 ms | 0.138 ms | 6.5x faster |
| high-entropy | 0.772 ms | 0.141 ms | 5.5x faster |
| read one text column | repetitive | 0.856 ms | 0.098 ms | 8.7x faster |
| high-entropy | 0.766 ms | 0.089 ms | 8.6x faster |
| read one row | repetitive | 0.856 ms | 0.018 ms | 47x faster |
| high-entropy | 0.749 ms | 0.018 ms | 41x faster |
| write every value | repetitive | 1.17 ms | 1.07 ms | 1.1x faster |
| high-entropy | 1.34 ms | 1.29 ms | about the same |
C
cJSON, the library most C code uses, and yyjson, one of the fastest JSON parsers there is, against jj_parse() and the accessors. Each run parses and then reads what the task asks for: a number as a double, checked against its grammar as the JSON parsers check it, and text as a pointer and a length. There is no C encoder, so there is no write task.
| 50,000 rows | data | cJSON | yyjson | jalapenojson | vs cJSON | vs yyjson |
|---|
| read every value | repetitive | 49.7 ms | 6.03 ms | 4.10 ms | 12x faster | 1.5x faster |
| high-entropy | 54.6 ms | 6.79 ms | 3.87 ms | 14x faster | 1.8x faster |
| read one number column | repetitive | 48.0 ms | 5.72 ms | 1.13 ms | 43x faster | 5.1x faster |
| high-entropy | 49.9 ms | 6.63 ms | 1.16 ms | 43x faster | 5.7x faster |
| read one text column | repetitive | 47.7 ms | 5.73 ms | 0.407 ms | 117x faster | 14x faster |
| high-entropy | 47.9 ms | 6.50 ms | 0.422 ms | 114x faster | 15x faster |
| read one row | repetitive | 48.1 ms | 5.87 ms | 0.059 ms | 820x faster | 100x faster |
| high-entropy | 48.6 ms | 6.54 ms | 0.085 ms | 574x faster | 77x faster |
1,000 rows
| 1,000 rows | data | cJSON | yyjson | jalapenojson | vs cJSON | vs yyjson |
|---|
| read every value | repetitive | 0.560 ms | 0.092 ms | 0.071 ms | 7.9x faster | 1.3x faster |
| high-entropy | 0.597 ms | 0.092 ms | 0.069 ms | 8.6x faster | 1.3x faster |
| read one number column | repetitive | 0.554 ms | 0.081 ms | 0.017 ms | 33x faster | 4.8x faster |
| high-entropy | 0.594 ms | 0.084 ms | 0.020 ms | 29x faster | 4.1x faster |
| read one text column | repetitive | 0.548 ms | 0.078 ms | 0.008 ms | 71x faster | 10x faster |
| high-entropy | 0.585 ms | 0.081 ms | 0.007 ms | 85x faster | 12x faster |
| read one row | repetitive | 0.535 ms | 0.073 ms | 0.001 ms | 733x faster | 100x faster |
| high-entropy | 0.575 ms | 0.078 ms | 0.001 ms | 776x faster | 105x faster |
WebAssembly
jalapenojson's C reader compiled to WebAssembly. Ubuntu clang version 18.1.3 (1ubuntu1) built jalapenojson.h for wasm32-wasi with -O2, against wasi-libc, into a module of 34 KB, 13 KB gzipped. Two questions, measured apart: whether reading through it is faster than the JavaScript reader, and whether jalapenojson's lead over the JSON parsers survives the move to WebAssembly.
WebAssembly cannot make a JavaScript string or object, so bench/wasm.c converts each number and copies each text value into one run of bytes in the module's memory, and bench/wasm.mjs turns what it leaves into the values the JavaScript reader hands back: the run of text is decoded once and each value cut out of it, and the rows are built in JavaScript. Every call copies the document into the module's memory first, because that is the only memory WebAssembly reads, and the copy is timed. The tasks are the JavaScript section's, but for writing, on Node 24.21.0, warmed up the same way.
| 50,000 rows | data | JSON | JavaScript | WebAssembly | vs JSON | vs JavaScript |
|---|
| read every value | repetitive | 24.4 ms | 20.9 ms | 20.1 ms | 1.2x faster | about the same |
| high-entropy | 31.2 ms | 17.2 ms | 20.8 ms | 1.5x faster | 1.2x slower |
| read every value, as columns | repetitive | 32.6 ms | 17.3 ms | 13.6 ms | 2.4x faster | 1.3x faster |
| high-entropy | 39.4 ms | 14.5 ms | 17.1 ms | 2.3x faster | 1.2x slower |
| read one number column | repetitive | 25.3 ms | 1.69 ms | 1.66 ms | 15x faster | about the same |
| high-entropy | 31.7 ms | 1.63 ms | 1.71 ms | 18x faster | 1.1x slower |
| read one text column | repetitive | 26.0 ms | 4.92 ms | 3.17 ms | 8.2x faster | 1.6x faster |
| high-entropy | 33.3 ms | 2.38 ms | 3.44 ms | 9.7x faster | 1.4x slower |
| read one row | repetitive | 23.6 ms | 0.104 ms | 0.267 ms | 88x faster | 2.6x slower |
| high-entropy | 30.8 ms | 0.122 ms | 0.341 ms | 91x faster | 2.8x slower |
The first call
One run in a fresh process, the median of several, as for the JavaScript reader. The module is compiled and instantiated before the clock starts, as the JavaScript reader is imported before it starts, so what a first call pays for is what V8 compiles as it goes, in either.
| 1,000 rows, first call | data | JSON | JavaScript | WebAssembly | vs JSON | vs JavaScript |
|---|
| read every value | repetitive | 0.993 ms | 4.85 ms | 2.53 ms | 2.5x slower | 1.9x faster |
| high-entropy | 1.19 ms | 3.85 ms | 2.59 ms | 2.2x slower | 1.5x faster |
| read one number column | repetitive | 1.11 ms | 1.77 ms | 1.32 ms | 1.2x slower | 1.3x faster |
| high-entropy | 1.41 ms | 1.88 ms | 1.24 ms | 1.1x faster | 1.5x faster |
| read one text column | repetitive | 1.12 ms | 2.53 ms | 1.69 ms | 1.5x slower | 1.5x faster |
| high-entropy | 1.22 ms | 1.80 ms | 1.20 ms | about the same | 1.5x faster |
| read one row | repetitive | 1.04 ms | 1.34 ms | 1.31 ms | 1.3x slower | about the same |
| high-entropy | 1.12 ms | 1.35 ms | 1.55 ms | 1.4x slower | 1.1x slower |
| 50,000 rows, first call | data | JSON | JavaScript | WebAssembly | vs JSON | vs JavaScript |
|---|
| read every value | repetitive | 42.9 ms | 51.4 ms | 44.9 ms | about the same | 1.1x faster |
| high-entropy | 60.5 ms | 42.3 ms | 46.6 ms | 1.3x faster | 1.1x slower |
| read one number column | repetitive | 46.1 ms | 9.75 ms | 7.57 ms | 6.1x faster | 1.3x faster |
| high-entropy | 58.3 ms | 11.2 ms | 8.47 ms | 6.9x faster | 1.3x faster |
| read one text column | repetitive | 44.4 ms | 18.7 ms | 10.5 ms | 4.2x faster | 1.8x faster |
| high-entropy | 57.5 ms | 12.4 ms | 13.6 ms | 4.2x faster | 1.1x slower |
| read one row | repetitive | 50.0 ms | 2.50 ms | 3.14 ms | 16x faster | 1.3x slower |
| high-entropy | 55.3 ms | 2.54 ms | 3.40 ms | 16x faster | 1.3x slower |
In a browser
The first read in a fresh page of Chromium 141.0.7390.37, the median of several pages, as in the browser section. The document is the one the JavaScript reader reads, so it downloads in the same time, and only the read is shown. Fetching, compiling and instantiating the module took 3.23 ms in a fresh page, the median over those pages, which a page does once and can do while the document downloads.
| 50,000 rows, first read in a page | data | JSON | JavaScript | WebAssembly | vs JSON | vs JavaScript |
|---|
| read every value | repetitive | 29.2 ms | 44.5 ms | 41.3 ms | 1.4x slower | 1.1x faster |
| high-entropy | 33.9 ms | 41.4 ms | 42.3 ms | 1.2x slower | about the same |
| read one number column | repetitive | 31.2 ms | 5.73 ms | 6.70 ms | 4.7x faster | 1.2x slower |
| high-entropy | 37.4 ms | 6.29 ms | 7.71 ms | 4.9x faster | 1.2x slower |
| read one row | repetitive | 30.5 ms | 2.38 ms | 2.76 ms | 11x faster | 1.2x slower |
| high-entropy | 33.5 ms | 2.44 ms | 2.97 ms | 11x faster | 1.2x slower |
| 1,000 rows, first read in a page | data | JSON | JavaScript | WebAssembly | vs JSON | vs JavaScript |
|---|
| read every value | repetitive | 0.615 ms | 4.36 ms | 2.46 ms | 4.0x slower | 1.8x faster |
| high-entropy | 0.615 ms | 3.79 ms | 2.42 ms | 3.9x slower | 1.6x faster |
| read one number column | repetitive | 0.725 ms | 1.70 ms | 1.17 ms | 1.6x slower | 1.5x faster |
| high-entropy | 0.760 ms | 2.10 ms | 1.12 ms | 1.5x slower | 1.9x faster |
| read one row | repetitive | 0.705 ms | 1.30 ms | 1.22 ms | 1.7x slower | 1.1x faster |
| high-entropy | 0.645 ms | 1.27 ms | 1.23 ms | 1.9x slower | about the same |
Inside WebAssembly
The C section's measurement compiled whole: bench/c.c, with cJSON and yyjson, built for wasm32-wasi the same way and run by Node's WASI. Numbers and text stay inside the module, as they stay inside the process in C, so nothing crosses into JavaScript, and this is WebAssembly's own speed.
| 50,000 rows | data | cJSON | yyjson | jalapenojson | vs cJSON | vs yyjson |
|---|
| read every value | repetitive | 37.7 ms | 8.17 ms | 5.94 ms | 6.3x faster | 1.4x faster |
| high-entropy | 50.8 ms | 8.39 ms | 7.15 ms | 7.1x faster | 1.2x faster |
| read one number column | repetitive | 37.8 ms | 7.93 ms | 1.19 ms | 32x faster | 6.7x faster |
| high-entropy | 47.8 ms | 8.23 ms | 1.25 ms | 38x faster | 6.6x faster |
| read one text column | repetitive | 36.6 ms | 7.65 ms | 1.13 ms | 32x faster | 6.8x faster |
| high-entropy | 47.8 ms | 8.10 ms | 1.37 ms | 35x faster | 5.9x faster |
| read one row | repetitive | 35.7 ms | 7.16 ms | 0.060 ms | 599x faster | 120x faster |
| high-entropy | 47.8 ms | 7.65 ms | 0.087 ms | 550x faster | 88x faster |
Against the same code built natively, in the C section, a run in WebAssembly takes this many times as long at 50,000 rows: 0.7x to 1.0x with cJSON, 1.2x to 1.4x with yyjson, and 1.0x to 3.2x with jalapenojson.
1,000 rows
| 1,000 rows | data | JSON | JavaScript | WebAssembly | vs JSON | vs JavaScript |
|---|
| read every value | repetitive | 0.422 ms | 0.337 ms | 0.324 ms | 1.3x faster | about the same |
| high-entropy | 0.422 ms | 0.289 ms | 0.346 ms | 1.2x faster | 1.2x slower |
| read every value, as columns | repetitive | 0.527 ms | 0.232 ms | 0.195 ms | 2.7x faster | 1.2x faster |
| high-entropy | 0.540 ms | 0.187 ms | 0.225 ms | 2.4x faster | 1.2x slower |
| read one number column | repetitive | 0.428 ms | 0.026 ms | 0.021 ms | 20x faster | 1.2x faster |
| high-entropy | 0.423 ms | 0.030 ms | 0.026 ms | 16x faster | 1.2x faster |
| read one text column | repetitive | 0.422 ms | 0.056 ms | 0.034 ms | 12x faster | 1.7x faster |
| high-entropy | 0.422 ms | 0.024 ms | 0.029 ms | 15x faster | 1.2x slower |
| read one row | repetitive | 0.419 ms | 0.006 ms | 0.005 ms | 91x faster | 1.4x faster |
| high-entropy | 0.416 ms | 0.007 ms | 0.006 ms | 73x faster | 1.1x faster |
| 1,000 rows | data | cJSON | yyjson | jalapenojson | vs cJSON | vs yyjson |
|---|
| read every value | repetitive | 0.634 ms | 0.141 ms | 0.099 ms | 6.4x faster | 1.4x faster |
| high-entropy | 0.832 ms | 0.141 ms | 0.111 ms | 7.5x faster | 1.3x faster |
| read one number column | repetitive | 0.619 ms | 0.137 ms | 0.016 ms | 38x faster | 8.5x faster |
| high-entropy | 0.810 ms | 0.136 ms | 0.021 ms | 38x faster | 6.4x faster |
| read one text column | repetitive | 0.613 ms | 0.127 ms | 0.010 ms | 63x faster | 13x faster |
| high-entropy | 0.809 ms | 0.130 ms | 0.010 ms | 80x faster | 13x faster |
| read one row | repetitive | 0.612 ms | 0.123 ms | 0.001 ms | 714x faster | 143x faster |
| high-entropy | 0.805 ms | 0.126 ms | 0.001 ms | 918x faster | 143x faster |
How it was measured
- Each number comes from its own process, started for that one measurement, so no reader runs in a process another reader has warmed.
- Warmed up means the task ran until it had run for 200 ms, and then the fastest of at least 15 more runs and at least 500 ms was kept. The number shown is the median of that over 5 rounds, each of which ran every measurement once, in a different order.
- Every run's result is checked: a count of the values it read, their sum, and a CRC-32 of their text, against the same worked out from the rows the files were written from. A run that read something else stops the benchmark.
- The input is bytes in memory for both formats. Freeing memory is not timed in C; in JavaScript and Python the garbage collector runs when it runs.
- In JavaScript and Python jalapenojson checks every date it reads, and Python gets
date objects; JSON has no dates, so its readers hand the same values back as unchecked strings. In C every reader hands a date back as text, and so does the WebAssembly reader, having checked it. - The WebAssembly modules are built by
bench/run.sh on every run, from bench/wasm.c and bench/c.c, and are measured by the same workers and checked against the same checksums as everything else.