Title: buffer: let Buffer.of use heap by ChALkeR · Pull Request #60503 · nodejs/node · GitHub
Open Graph Title: buffer: let Buffer.of use heap by ChALkeR · Pull Request #60503 · nodejs/node
X Title: buffer: let Buffer.of use heap by ChALkeR · Pull Request #60503 · nodejs/node
Description: See also #60372. This is a somewhat less performant version than that PR, but significantly faster than main and is non semver-major (so it can be backported) and does not need doc changes. Buffer.of is usually used on small static sizes (checked with GitHub codesearch) The assumption that createUnsafeBuffer(size) is faster than new Uint8Array(size) / new FastBuffer(size) is incorrect for small sizes, as the latter does not call our allocator at all when it can go to heap, and the former is always an alloc. Not letting it go to heap is hurting performance, direct allocations are slow. See #26301 for context But even past the v8_typed_array_max_size_in_heap size (which is 64 bytes in the default config), this is still not worse than the old version way past expected Buffer.of sizes Before: % out/Release/node.0 benchmark/buffers/buffer-of.js buffers/buffer-of.js n=500000 len=0: 24,633,954.827485334 buffers/buffer-of.js n=500000 len=1: 26,160,564.38801611 buffers/buffer-of.js n=500000 len=2: 26,280,949.92493504 buffers/buffer-of.js n=500000 len=8: 22,938,007.012818534 buffers/buffer-of.js n=500000 len=64: 9,478,358.537868412 buffers/buffer-of.js n=500000 len=256: 2,702,711.2345046536 buffers/buffer-of.js n=500000 len=1024: 974,881.6079890658 buffers/buffer-of.js n=500000 len=2048: 528,368.570893787 After: % out/Release/node.2 benchmark/buffers/buffer-of.js buffers/buffer-of.js n=500000 len=0: 33,703,264.18068379 buffers/buffer-of.js n=500000 len=1: 35,216,496.263314925 buffers/buffer-of.js n=500000 len=2: 34,097,195.761377595 buffers/buffer-of.js n=500000 len=8: 27,875,878.880465902 buffers/buffer-of.js n=500000 len=64: 10,335,418.86238334 buffers/buffer-of.js n=500000 len=256: 2,763,676.639751257 buffers/buffer-of.js n=500000 len=1024: 981,007.050158241 buffers/buffer-of.js n=500000 len=2048: 523,017.20255880937 For comparison, #60372 (even faster, but does that via pooling): % ./out/Release/node.pooled benchmark/buffers/buffer-of.js buffers/buffer-of.js n=500000 len=0: 33,882,981.248046815 buffers/buffer-of.js n=500000 len=1: 44,826,164.135482594 buffers/buffer-of.js n=500000 len=2: 44,895,948.02845056 buffers/buffer-of.js n=500000 len=8: 31,774,014.66683433 buffers/buffer-of.js n=500000 len=64: 10,511,875.791675644 buffers/buffer-of.js n=500000 len=256: 3,666,954.9211037415 buffers/buffer-of.js n=500000 len=1024: 1,082,339.2273017906 buffers/buffer-of.js n=500000 len=2048: 554,083.8215035282 Realistically, sizes 0-8 are most important. Benchmark code (taken from #60372 with some adjustments): 'use strict'; const common = require('../common.js'); // Measure Buffer.of(...items) throughput for various lengths. // We prebuild the items array to avoid measuring array construction, // and vary the effective iterations with length to keep total work reasonable. const bench = common.createBenchmark(main, { len: [0, 1, 2, 8, 64, 256, 1024, 2048], n: [5e5], }); function main({ len, n }) { if (len < 10) n *= 10; // noisy otherwise // Inline small numbers calls as this is fast enough for small changes to be significant switch (len) { case 0: bench.start(); for (let i = 0; i < n; i++) Buffer.of(); bench.end(n); break; case 1: bench.start(); for (let i = 0; i < n; i++) Buffer.of(0); bench.end(n); break; case 2: bench.start(); for (let i = 0; i < n; i++) Buffer.of(0, 1); bench.end(n); break; case 8: bench.start(); for (let i = 0; i < n; i++) Buffer.of(0, 1, 2, 3, 4, 5, 6, 7); bench.end(n); break; default: { const items = new Array(len); for (let i = 0; i < len; i++) items[i] = i & 0xFF; bench.start(); for (let i = 0; i < n; i++) { Buffer.of(...items); } bench.end(n); } } }
Open Graph Description: See also #60372. This is a somewhat less performant version than that PR, but significantly faster than main and is non semver-major (so it can be backported) and does not need doc changes. Buffer....
X Description: See also #60372. This is a somewhat less performant version than that PR, but significantly faster than main and is non semver-major (so it can be backported) and does not need doc changes. Buffer....
Opengraph URL: https://github.com/nodejs/node/pull/60503
X: @github
Domain: redirect.github.com
| route-pattern | /:user_id/:repository/pull/:id/files/:range(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:6a62b23f-e428-681c-6442-0d308337f335 |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | 9C6E:229D5F:37431C2:49731AC:6A655C30 |
| html-safe-nonce | 44f7aa98cf8a6fb7c2409215fdd1f6a5e3249db4f94d35047e109fdc15885e88 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5QzZFOjIyOUQ1RjozNzQzMUMyOjQ5NzMxQUM6NkE2NTVDMzAiLCJ2aXNpdG9yX2lkIjoiMTE5NjUyNzA5NzA1Mjc2NDY0IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 1fc4cd43b47bdd6838d9bb00eb8469a693a9abd6a1762f8f51931cbe647e2536 |
| hovercard-subject-tag | pull_request:2965045375 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/nodejs/node/pull/60503/files/1a8aac15fc296b67e38b6d9ef9f5a1239aa3b8ae |
| twitter:image | https://avatars.githubusercontent.com/u/291301?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/291301?s=400&v=4 |
| og:image:alt | See also #60372. This is a somewhat less performant version than that PR, but significantly faster than main and is non semver-major (so it can be backported) and does not need doc changes. Buffer.... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 52c76df668885aaff23b50bdca1fa1ea44ac9c1553e888ebc70ff1e4daa4625b |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/nodejs/node git https://github.com/nodejs/node.git |
| octolytics-dimension-user_id | 9950313 |
| octolytics-dimension-user_login | nodejs |
| octolytics-dimension-repository_id | 27193779 |
| octolytics-dimension-repository_nwo | nodejs/node |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27193779 |
| octolytics-dimension-repository_network_root_nwo | nodejs/node |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 309153364422b3c499922d1a2a6404910a58ed8e |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width