Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad base64 decoding performance with node:buffer #24323

Open
dsherret opened this issue Jun 24, 2024 · 2 comments · Fixed by #24567
Open

Bad base64 decoding performance with node:buffer #24323

dsherret opened this issue Jun 24, 2024 · 2 comments · Fixed by #24567
Assignees
Labels
node API polyfill Related to various "node:*" modules APIs perf performance related

Comments

@dsherret
Copy link
Member

https://x.com/justjs14/status/1805074553384697918

Code: https://github.com/just-js/lo-bench/blob/97001c993e1e46173d1257182e0af99534fad150/base64/base64.mjs

Version: Deno 1.44.4

@littledivy
Copy link
Member

Buffer.from('base64') perf fixed by #24346

@nathanwhit
Copy link
Member

nathanwhit commented Jul 30, 2024

I'm not sure I would consider this resolved. Re-running the benchmark with the most recent optimizations shows we're still behind by a substantial margin in a lot of cases (especially Buffer.write):
(Run on an M3 Max, on the latest canary)

node v deno v bun (Buffer.from)

32           ops/sec/core thru/core    ratio
node             14499935   463.99 MBps      1 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno             12243805   391.80 MBps   0.84 🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣
bun               8423546   269.55 MBps   0.58 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡
512          ops/sec/core thru/core    ratio
node              6910694     3.53 GBps      1 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno              2437785     1.24 GBps   0.35 🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣
bun               4886867     2.50 GBps    0.7 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡
65536        ops/sec/core thru/core    ratio
node                44403     2.90 GBps   0.43 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno                31183     2.04 GBps    0.3 🟣🟣🟣🟣🟣🟣🟣🟣🟣
bun                101301     6.63 GBps      1 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡
524288       ops/sec/core thru/core    ratio
node                 6122     3.20 GBps   0.46 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno                 4244     2.22 GBps   0.32 🟣🟣🟣🟣🟣🟣🟣🟣🟣
bun                 13145     6.89 GBps      1 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡
8388608      ops/sec/core thru/core    ratio
node                  646     5.41 GBps   0.76 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno                  293     2.45 GBps   0.34 🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣
bun                   841     7.05 GBps      1 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡


node v deno v bun (Buffer.write)

32           ops/sec/core thru/core    ratio
node             19724417   631.18 MBps   0.72 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno             19997682   639.92 MBps   0.73 🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣🟣
bun              27151381   868.84 MBps      1 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡
512          ops/sec/core thru/core    ratio
node              9461650     4.84 GBps   0.74 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno              3072942     1.57 GBps   0.24 🟣🟣🟣🟣🟣🟣🟣
bun              12660528     6.48 GBps      1 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡
65536        ops/sec/core thru/core    ratio
node               122880     8.05 GBps   0.68 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno                25582     1.67 GBps   0.14 🟣🟣🟣🟣
bun                180261    11.81 GBps      1 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡
524288       ops/sec/core thru/core    ratio
node                17687     9.27 GBps   0.78 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno                 3286     1.72 GBps   0.14 🟣🟣🟣🟣
bun                 22561    11.82 GBps      1 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡
8388608      ops/sec/core thru/core    ratio
node                 1399    11.73 GBps      1 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
deno                  187     1.56 GBps   0.13 🟣🟣🟣🟣
bun                  1394    11.69 GBps   0.99 🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡🟡

@nathanwhit nathanwhit reopened this Jul 30, 2024
crowlKats pushed a commit that referenced this issue Jul 31, 2024
Fixes #24323

- Use a Buffer pool for `fromString`
- Implement fast call base64 writes
- Direct from string `create` method for each encoding op

```
$ deno bench -A bench.mjs # 1.45.1+fee4d3a
cpu: Apple M1 Pro
runtime: deno 1.45.1+fee4d3a (aarch64-apple-darwin)

benchmark                time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------- -----------------------------
Buffer.from base64      550 ns/iter     (490 ns … 1'265 ns)    572 ns    606 ns  1'265 ns
Buffer#write base64     285 ns/iter       (259 ns … 371 ns)    307 ns    347 ns    360 ns

$ ~/gh/deno/target/release/deno bench -A bench.mjs # this PR
cpu: Apple M1 Pro
runtime: deno dev (aarch64-apple-darwin)

benchmark                time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------- -----------------------------
Buffer.from base64      151 ns/iter       (145 ns … 770 ns)    148 ns    184 ns    648 ns
Buffer#write base64   62.58 ns/iter     (60.79 ns … 157 ns)  61.65 ns  75.79 ns    141 ns

$ node bench.mjs # v22.4.0
cpu: Apple M1 Pro
runtime: node v22.4.0 (arm64-darwin)

benchmark                time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------- -----------------------------
Buffer.from base64      163 ns/iter     (96.92 ns … 375 ns)  99.45 ns    127 ns    220 ns
Buffer#write base64   75.48 ns/iter     (74.97 ns … 134 ns)  75.17 ns  81.83 ns  96.84 ns
```

(cherry picked from commit 1ba88a7)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
node API polyfill Related to various "node:*" modules APIs perf performance related
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants