Divy Srivastava
1ba88a7892
perf(ext/node): improve Buffer
from string performance ( #24567 )
...
Fixes https://github.com/denoland/deno/issues/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
```
2024-07-30 18:09:55 +05:30
ud2
86e0292733
perf(ext/node): improve Buffer.from(buffer)
( #24352 )
...
Benchmark code from #24341 .
```shellsession
$ deno run --allow-hrtime bench.mjs
6479.111583
$ target/release/deno run --allow-hrtime bench.mjs
962.753875
$ node bench.mjs
855.174875
```
2024-06-26 17:11:56 -04:00
David Sherret
77ba0019e7
Revert "perf: improve Buffer.from(buf) by 29x" ( #24351 )
...
https://github.com/denoland/deno/pull/24341#discussion_r1655247367
Reverts denoland/deno#24341
2024-06-26 16:23:09 -04:00
Divy Srivastava
6da87450ed
perf: improve Buffer.from(buf) by 29x ( #24341 )
2024-06-26 06:24:48 -07:00
Bartek Iwańczuk
6a356aff13
chore: sync up Node.js test files for v20.11.1 ( #24066 )
...
Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
2024-06-11 11:41:44 +00:00
snek
8f2d171404
feat(node): buffer isUtf8/isAscii ( #23928 )
...
Fixes: https://github.com/denoland/deno/issues/23657
Implements `isUtf8` and `isAscii` as ops.
2024-05-21 15:50:59 -07:00
Kenta Moriuchi
515a34b4de
refactor: use core.ensureFastOps()
( #21888 )
2024-01-10 15:37:25 -07:00
Yoshiya Hinosawa
567d7ff923
fix(ext/node): fix Buffer.copy when sourceStart > source.length ( #21345 )
2023-11-28 22:28:07 +09:00
Aapo Alasuutari
effb5e1ce4
fix(node/buffer): utf8ToBytes should return a Uint8Array ( #20769 )
2023-10-08 11:09:50 +09:00
Divy Srivastava
1cda3840ff
perf(node): use faster utf8 byte length in Buffer#from ( #20746 )
...
Use the `core.byteLength` op for string utf8 length calculation in
`node:buffer`
```
# This patch
file:///Users/divy/gh/deno/buffer.mjs
benchmark time (avg) iter/s (min … max) p75 p99 p995
----------------------------------------------------------------- -----------------------------
Buffer#from 272.11 ns/iter 3,675,029.3 (268.41 ns … 301.15 ns) 271.62 ns 295.5 ns 301.15 ns
# Deno 1.37.1
file:///Users/divy/gh/deno/buffer.mjs
benchmark time (avg) iter/s (min … max) p75 p99 p995
----------------------------------------------------------------- -----------------------------
Buffer#from 411.28 ns/iter 2,431,428.8 (393.82 ns … 439.92 ns) 418.85 ns 434.4 ns 439.92 ns
```
2023-09-30 20:04:40 +05:30
Aapo Alasuutari
cb9ab9c3ac
fix(ext/node): Fix invalid length variable reference in blitBuffer ( #20648 )
2023-09-24 13:48:23 +03:00
Aapo Alasuutari
9d6584c16f
perf(ext/node): Optimise Buffer string operations ( #20158 )
...
Extracted from https://github.com/denoland/deno/pull/17815
Optimise Buffer's string operations, most significantly when dealing
with ASCII and UTF-16. Base64 and HEX encodings are affected to much
lesser degrees.
## Performance
### String length 15
With very small strings we're at break-even or sometimes even lose a tad
bit of performance from creating a `DataView` that ends up not paying
for itself.
**This PR:**
```
benchmark time (avg) iter/s (min … max) p75 p99 p995
-------------------------------------------------------------------------------------------------------------- -----------------------------
Buffer.from ascii string 1.15 µs/iter 871,388.6 (728.78 ns … 1.56 µs) 1.23 µs 1.56 µs 1.56 µs
Buffer.from base64 string 1.63 µs/iter 612,790.9 (1.31 µs … 1.96 µs) 1.77 µs 1.96 µs 1.96 µs
Buffer.from utf16 string 1.41 µs/iter 707,396.3 (915.24 ns … 1.93 µs) 1.61 µs 1.93 µs 1.93 µs
Buffer.from hex string 1.87 µs/iter 535,357.9 (1.56 µs … 2.19 µs) 2 µs 2.19 µs 2.19 µs
Buffer.toString ascii string 154.58 ns/iter 6,469,162.8 (149.69 ns … 198 ns) 154.51 ns 182.89 ns 191.91 ns
Buffer.toString base64 string 161.65 ns/iter 6,186,189.6 (150.91 ns … 181.15 ns) 165.18 ns 171.87 ns 174.94 ns
Buffer.toString utf16 string 292.74 ns/iter 3,415,959.8 (285.43 ns … 312.47 ns) 295.25 ns 310.47 ns 312.47 ns
Buffer.toString hex string 89.61 ns/iter 11,159,315.6 (81.09 ns … 123.77 ns) 91.09 ns 113.62 ns 119.28 ns
```
**Main:**
```
benchmark time (avg) iter/s (min … max) p75 p99 p995
-------------------------------------------------------------------------------------------------------------- -----------------------------
Buffer.from ascii string 1.26 µs/iter 794,875.8 (1.07 µs … 1.46 µs) 1.31 µs 1.46 µs 1.46 µs
Buffer.from base64 string 1.65 µs/iter 607,853.3 (1.38 µs … 2.01 µs) 1.69 µs 2.01 µs 2.01 µs
Buffer.from utf16 string 1.34 µs/iter 744,894.6 (1.09 µs … 1.55 µs) 1.45 µs 1.55 µs 1.55 µs
Buffer.from hex string 2.01 µs/iter 496,345.8 (1.54 µs … 2.6 µs) 2.26 µs 2.6 µs 2.6 µs
Buffer.toString ascii string 150.16 ns/iter 6,659,630.5 (144.99 ns … 166.68 ns) 152.4 ns 157.26 ns 159.14 ns
Buffer.toString base64 string 164.73 ns/iter 6,070,692.0 (158.77 ns … 185.63 ns) 168.48 ns 175.74 ns 176.68 ns
Buffer.toString utf16 string 150.61 ns/iter 6,639,864.0 (148.2 ns … 168.29 ns) 150.93 ns 157.21 ns 168.15 ns
Buffer.toString hex string 94.21 ns/iter 10,614,972.9 (86.21 ns … 98.75 ns) 95.43 ns 97.99 ns 98.21 ns
```
### String length 1500
With moderate lengths we already see great upsides for `Buffer.from()`
with ASCII and UTF-16.
**This PR:**
```
benchmark time (avg) iter/s (min … max) p75 p99 p995
-------------------------------------------------------------------------------------------------------------- -----------------------------
Buffer.from ascii string 5.79 µs/iter 172,562.6 (4.72 µs … 4.71 ms) 5.04 µs 10.3 µs 11.67 µs
Buffer.from base64 string 5.08 µs/iter 196,678.9 (4.97 µs … 5.76 µs) 5.08 µs 5.76 µs 5.76 µs
Buffer.from utf16 string 9.68 µs/iter 103,316.5 (7.14 µs … 3.44 ms) 10.32 µs 13.42 µs 15.21 µs
Buffer.from hex string 53.7 µs/iter 18,620.2 (49.37 µs … 2.2 ms) 54.74 µs 72.2 µs 81.07 µs
Buffer.toString ascii string 6.63 µs/iter 150,761.3 (5.59 µs … 1.11 ms) 6.08 µs 15.68 µs 24.77 µs
Buffer.toString base64 string 460.57 ns/iter 2,171,224.4 (448.33 ns … 511.73 ns) 465.05 ns 495.54 ns 511.73 ns
Buffer.toString utf16 string 6.52 µs/iter 153,287.0 (6.47 µs … 6.66 µs) 6.53 µs 6.66 µs 6.66 µs
Buffer.toString hex string 3.68 µs/iter 271,965.4 (3.64 µs … 3.82 µs) 3.68 µs 3.82 µs 3.82 µs
```
**Main:**
```
benchmark time (avg) iter/s (min … max) p75 p99 p995
-------------------------------------------------------------------------------------------------------------- -----------------------------
Buffer.from ascii string 11.46 µs/iter 87,298.1 (8.53 µs … 834.1 µs) 9.61 µs 83.31 µs 87.3 µs
Buffer.from base64 string 5.4 µs/iter 185,027.8 (5.07 µs … 7.49 µs) 5.44 µs 7.49 µs 7.49 µs
Buffer.from utf16 string 20.3 µs/iter 49,270.8 (13.55 µs … 649.11 µs) 18.8 µs 113.93 µs 125.17 µs
Buffer.from hex string 52.03 µs/iter 19,218.9 (48.74 µs … 2.59 ms) 52.84 µs 67.05 µs 73.56 µs
Buffer.toString ascii string 6.46 µs/iter 154,822.5 (6.32 µs … 6.69 µs) 6.52 µs 6.69 µs 6.69 µs
Buffer.toString base64 string 440.19 ns/iter 2,271,764.6 (427 ns … 490.77 ns) 444.74 ns 484.64 ns 490.77 ns
Buffer.toString utf16 string 6.89 µs/iter 145,106.7 (6.81 µs … 7.24 µs) 6.91 µs 7.24 µs 7.24 µs
Buffer.toString hex string 3.66 µs/iter 273,456.5 (3.6 µs … 4.02 µs) 3.64 µs 4.02 µs 4.02 µs
```
### String length 2^20
With massive lengths we the difference in ASCII and UTF-16 parsing
performance is enormous.
**This PR:**
```
benchmark time (avg) iter/s (min … max) p75 p99 p995
-------------------------------------------------------------------------------------------------------------------- -----------------------------
Buffer.from ascii string 4.1 ms/iter 243.7 (2.64 ms … 6.74 ms) 4.43 ms 6.26 ms 6.74 ms
Buffer.from base64 string 3.74 ms/iter 267.6 (2.91 ms … 4.92 ms) 3.96 ms 4.31 ms 4.92 ms
Buffer.from utf16 string 7.72 ms/iter 129.5 (5.91 ms … 11.03 ms) 7.97 ms 11.03 ms 11.03 ms
Buffer.from hex string 35.72 ms/iter 28.0 (34.71 ms … 38.42 ms) 35.93 ms 38.42 ms 38.42 ms
Buffer.toString ascii string 78.92 ms/iter 12.7 (42.72 ms … 94.13 ms) 91.64 ms 94.13 ms 94.13 ms
Buffer.toString base64 string 833.62 µs/iter 1,199.6 (638.05 µs … 5.97 ms) 826.86 µs 2.45 ms 2.48 ms
Buffer.toString utf16 string 79.35 ms/iter 12.6 (69.72 ms … 88.9 ms) 86.66 ms 88.9 ms 88.9 ms
Buffer.toString hex string 31.04 ms/iter 32.2 (4.3 ms … 46.9 ms) 37.21 ms 46.9 ms 46.9 ms
```
**Main:**
```
benchmark time (avg) iter/s (min … max) p75 p99 p995
-------------------------------------------------------------------------------------------------------------------- -----------------------------
Buffer.from ascii string 18.66 ms/iter 53.6 (15.61 ms … 23.26 ms) 20.62 ms 23.26 ms 23.26 ms
Buffer.from base64 string 4.7 ms/iter 212.9 (2.94 ms … 9.07 ms) 4.65 ms 9.06 ms 9.07 ms
Buffer.from utf16 string 33.49 ms/iter 29.9 (31.24 ms … 35.67 ms) 34.08 ms 35.67 ms 35.67 ms
Buffer.from hex string 39.38 ms/iter 25.4 (38.66 ms … 42.36 ms) 39.58 ms 42.36 ms 42.36 ms
Buffer.toString ascii string 77.68 ms/iter 12.9 (67.46 ms … 95.68 ms) 84.71 ms 95.68 ms 95.68 ms
Buffer.toString base64 string 825.53 µs/iter 1,211.3 (655.38 µs … 6.69 ms) 816.62 µs 3.07 ms 3.13 ms
Buffer.toString utf16 string 76.54 ms/iter 13.1 (66.9 ms … 85.26 ms) 83.63 ms 85.26 ms 85.26 ms
Buffer.toString hex string 38.56 ms/iter 25.9 (33.83 ms … 46.56 ms) 45.33 ms 46.56 ms 46.56 ms
```
2023-09-07 14:41:16 -06:00
David Sherret
f3095b8d31
chore: upgrade to dprint 0.39 ( #19768 )
2023-07-08 18:34:08 +00:00
Kenta Moriuchi
e16b74d792
chore(ext/node): disable prefer-primordials on a per-file basis ( #19553 )
2023-06-27 15:18:22 +09:00
Leo Kettmeir
92e7287f4a
fix(node/buffer): make slice be the same as subarray ( #19481 )
2023-06-13 21:26:28 +02:00
Bartek Iwańczuk
72fe9bb470
refactor: rename InternalModuleLoader to ExtModuleLoader, use ext: scheme for snapshotted modules ( #18041 )
...
This commit renames "deno_core::InternalModuleLoader" to
"ExtModuleLoader" and changes the specifiers used by the
modules loaded from this loader to "ext:".
"internal:" scheme was really ambiguous and it's more characters than
"ext:", which should result in slightly smaller snapshot size.
Closes https://github.com/denoland/deno/issues/18020
2023-03-08 12:44:54 +01:00
Bartek Iwańczuk
b40086fd7d
refactor(core): include_js_files! 'dir' option doesn't change specifiers ( #18019 )
...
This commit changes "include_js_files!" macro from "deno_core"
in a way that "dir" option doesn't cause specifiers to be rewritten
to include it.
Example:
```
include_js_files! {
dir "js",
"hello.js",
}
```
The above definition required embedders to use:
`import ... from "internal:<ext_name>/js/hello.js"`.
But with this change, the "js" directory in which the files are stored
is an implementation detail, which for embedders results in:
`import ... from "internal:<ext_name>/hello.js"`.
The directory the files are stored in, is an implementation detail and
in some cases might result in a significant size difference for the
snapshot. As an example, in "deno_node" extension, we store the
source code in "polyfills" directory; which resulted in each specifier
to look like "internal:deno_node/polyfills/<module_name>", but with
this change it's "internal:deno_node/<module_name>".
Given that "deno_node" has over 100 files, many of them having
several import specifiers to the same extension, this change removes
10 characters from each import specifier.
2023-03-05 02:31:38 +00:00
Yoshiya Hinosawa
a01af067d7
test: add node compat tests ( #17805 )
2023-02-17 23:58:52 +09:00
Bartek Iwańczuk
d47147fb6a
feat(ext/node): embed std/node into the snapshot ( #17724 )
...
This commit moves "deno_std/node" in "ext/node" crate. The code is
transpiled and snapshotted during the build process.
During the first pass a minimal amount of work was done to create the
snapshot, a lot of code in "ext/node" depends on presence of "Deno"
global. This code will be gradually fixed in the follow up PRs to migrate
it to import relevant APIs from "internal:" modules.
Currently the code from snapshot is not used in any way, and all
Node/npm compatibility still uses code from
"https://deno.land/std/node " (or from the location specified by
"DENO_NODE_COMPAT_URL"). This will also be handled in a follow
up PRs.
---------
Co-authored-by: crowlkats <crowlkats@toaxl.com>
Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
2023-02-14 17:38:45 +01:00