From 026164446284339874ca8097b6223f12e003b4d6 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sat, 10 Aug 2024 20:49:11 +0200 Subject: [PATCH] buffer: optimize writing short strings PR-URL: https://github.com/nodejs/node/pull/54310 --- .../buffers/buffer-write-string-short.js | 20 +++++ benchmark/buffers/buffer-write-string.js | 74 ++++--------------- lib/buffer.js | 27 ++++++- 3 files changed, 60 insertions(+), 61 deletions(-) create mode 100644 benchmark/buffers/buffer-write-string-short.js diff --git a/benchmark/buffers/buffer-write-string-short.js b/benchmark/buffers/buffer-write-string-short.js new file mode 100644 index 00000000000000..366cd9ffd4aa91 --- /dev/null +++ b/benchmark/buffers/buffer-write-string-short.js @@ -0,0 +1,20 @@ +'use strict'; + +const common = require('../common.js'); +const bench = common.createBenchmark(main, { + len: [0, 1, 8, 16, 32], + fallback: [1, 0], + n: [1e6], +}); + +function main({ len, n, fallback }) { + const buf = Buffer.allocUnsafe(len); + const string = fallback && len > 0 + ? Buffer.from('a'.repeat(len - 1) + '€').toString() + : Buffer.from('a'.repeat(len)).toString() + bench.start(); + for (let i = 0; i < n; ++i) { + buf.write(string); + } + bench.end(n); +} diff --git a/benchmark/buffers/buffer-write-string.js b/benchmark/buffers/buffer-write-string.js index 9d9e8a93391737..720a27273bb045 100644 --- a/benchmark/buffers/buffer-write-string.js +++ b/benchmark/buffers/buffer-write-string.js @@ -2,67 +2,25 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { - encoding: [ - '', 'utf8', 'ascii', 'hex', 'utf16le', 'latin1', - ], - args: [ '', 'offset', 'offset+length' ], - len: [2048], + encoding: [ '', 'utf8', 'ascii' ], + len: [0, 1, 8, 16, 32], n: [1e6], }); -function main({ len, n, encoding, args }) { - let string; - let start = 0; +function main({ len, n, encoding }) { const buf = Buffer.allocUnsafe(len); - - switch (args) { - case 'offset': - string = 'a'.repeat(Math.floor(len / 2)); - start = len - string.length; - if (encoding) { - bench.start(); - for (let i = 0; i < n; ++i) { - buf.write(string, start, encoding); - } - bench.end(n); - } else { - bench.start(); - for (let i = 0; i < n; ++i) { - buf.write(string, start); - } - bench.end(n); - } - break; - case 'offset+length': - string = 'a'.repeat(len); - if (encoding) { - bench.start(); - for (let i = 0; i < n; ++i) { - buf.write(string, 0, buf.length, encoding); - } - bench.end(n); - } else { - bench.start(); - for (let i = 0; i < n; ++i) { - buf.write(string, 0, buf.length); - } - bench.end(n); - } - break; - default: - string = 'a'.repeat(len); - if (encoding) { - bench.start(); - for (let i = 0; i < n; ++i) { - buf.write(string, encoding); - } - bench.end(n); - } else { - bench.start(); - for (let i = 0; i < n; ++i) { - buf.write(string); - } - bench.end(n); - } + const string = 'a'.repeat(len); + if (encoding) { + bench.start(); + for (let i = 0; i < n; ++i) { + buf.write(string, encoding); + } + bench.end(n); + } else { + bench.start(); + for (let i = 0; i < n; ++i) { + buf.write(string); + } + bench.end(n); } } diff --git a/lib/buffer.js b/lib/buffer.js index 4e6031afdb3919..b1a8e05720ec0d 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -1082,10 +1082,10 @@ function _fill(buf, value, offset, end, encoding) { Buffer.prototype.write = function write(string, offset, length, encoding) { // Buffer#write(string); if (offset === undefined) { - return this.utf8Write(string, 0, this.length); - } + offset = 0; + length = this.length; // Buffer#write(string, encoding) - if (length === undefined && typeof offset === 'string') { + } else if (length === undefined && typeof offset === 'string') { encoding = offset; length = this.length; offset = 0; @@ -1108,6 +1108,27 @@ Buffer.prototype.write = function write(string, offset, length, encoding) { } } + const len = string?.length; + if ( + len <= 16 && + len <= length && + (!encoding || encoding === 'ascii' || encoding === 'utf8') && + typeof string === 'string' + ) { + for (let n = 0; true; n++) { + if (n === len) { + return len; + } + + const code = StringPrototypeCharCodeAt(string, n); + if (code >= 128) { + break; + } + + this[offset + n] = code; + } + } + if (!encoding) return this.utf8Write(string, offset, length);