Skip to content

Commit 728aed5

Browse files
committed
revert: drop PrefixSource.buffer() override that was slower than the default
Bench data (es6-promise.js fixture, 10 calls per task body): Source.buffer() default: ~1143 ops/s Hand-written single-pass buffer(): ~960 ops/s V8's optimized string replace + Buffer.from utf8 encode beats a JS-side indexOf+copy loop on typical ASCII inputs. The earlier commit shipped a slower buffer() in exchange for halved transient memory, but the CPU regression isn't worth that trade-off — and Source.buffer() already routes through this.source(), so subclasses that want the prefixed bytes don't lose anything. buffers() keeps the zero-copy splice implementation (~57% faster than the default [this.buffer()] path), which is the genuine win from addressing the TODO. https://claude.ai/code/session_01EHhGq9PRFRGefVtwwasCqZ
1 parent 81fe063 commit 728aed5

1 file changed

Lines changed: 8 additions & 42 deletions

File tree

lib/PrefixSource.js

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -62,51 +62,17 @@ class PrefixSource extends Source {
6262
return prefix + node.replace(REPLACE_REGEX, `\n${prefix}`);
6363
}
6464

65-
/**
66-
* Build the prefixed output directly from the underlying source's
67-
* buffer, skipping the regex replace + string-to-utf8 encoding that
68-
* `Source.prototype.buffer()` would do via `this.source()`. Two linear
69-
* passes (one to count `\n` followed by content, one to copy) so the
70-
* result buffer is sized exactly and written into a single allocation.
71-
* @returns {Buffer} buffer
72-
*/
73-
buffer() {
74-
const prefix = this._prefix;
75-
if (prefix.length === 0) return this._source.buffer();
76-
const content = this._source.buffer();
77-
const contentLen = content.length;
78-
if (contentLen === 0) return Buffer.from(prefix, "utf8");
79-
const prefixBuffer = Buffer.from(prefix, "utf8");
80-
const prefixLen = prefixBuffer.length;
81-
let extraPrefixes = 0;
82-
{
83-
let nl = content.indexOf(0x0a);
84-
while (nl !== -1 && nl + 1 < contentLen) {
85-
extraPrefixes++;
86-
nl = content.indexOf(0x0a, nl + 1);
87-
}
88-
}
89-
const result = Buffer.allocUnsafe(
90-
prefixLen + contentLen + prefixLen * extraPrefixes,
91-
);
92-
let writePos = prefixBuffer.copy(result, 0);
93-
let readPos = 0;
94-
while (readPos < contentLen) {
95-
const nl = content.indexOf(0x0a, readPos);
96-
const end = nl === -1 ? contentLen : nl + 1;
97-
writePos += content.copy(result, writePos, readPos, end);
98-
if (nl !== -1 && nl + 1 < contentLen) {
99-
writePos += prefixBuffer.copy(result, writePos);
100-
}
101-
readPos = end;
102-
}
103-
return result;
104-
}
105-
10665
/**
10766
* Returns a `Buffer[]` that concatenates to the prefixed source. Each
10867
* content chunk is a `subarray` of the underlying buffer (no copy);
109-
* only the prefix buffer is materialized.
68+
* only the prefix buffer is materialized. This skips both the regex
69+
* replace and the string-to-utf8 encoding that the default
70+
* `[this.buffer()]` path would do.
71+
*
72+
* `buffer()` itself stays on the `Source.prototype` default (which
73+
* goes through `this.source()` plus `Buffer.from`); benchmarking shows
74+
* V8's optimized string replace + utf8 encode beats a hand-written
75+
* single-pass copy here.
11076
* @returns {Buffer[]} buffers
11177
*/
11278
buffers() {

0 commit comments

Comments
 (0)