Skip to content

Commit

Permalink
stream: add fast-path for readable streams
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Nov 18, 2022
1 parent c74dbd2 commit 853ecc4
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 2 deletions.
35 changes: 35 additions & 0 deletions benchmark/streams/readable-encoding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict';

const common = require('../common');
const Readable = require('stream').Readable;

const BASE = 'hello world\n\n';

const bench = common.createBenchmark(main, {
encoding: ['utf-8', 'latin1'],
len: [256, 512, 1024 * 16],
op: ['unshift', 'push'],
n: [1e3]
});

function main({ n, encoding, len, op }) {
const b = BASE.repeat(len);
const s = new Readable({
objectMode: false,
});

bench.start();
switch (op) {
case 'unshift': {
for (let i = 0; i < n; i++)
s.unshift(b, encoding);
break;
}
case 'push': {
for (let i = 0; i < n; i++)
s.push(b, encoding);
break;
}
}
bench.end(n);
}
6 changes: 4 additions & 2 deletions lib/internal/streams/readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const {
Promise,
SafeSet,
SymbolAsyncIterator,
Symbol
Symbol,
} = primordials;

module.exports = Readable;
Expand Down Expand Up @@ -73,6 +73,7 @@ const kPaused = Symbol('kPaused');

const { StringDecoder } = require('string_decoder');
const from = require('internal/streams/from');
const { encodeWithFastPath } = require('internal/streams/utils');

ObjectSetPrototypeOf(Readable.prototype, Stream.prototype);
ObjectSetPrototypeOf(Readable, Stream);
Expand Down Expand Up @@ -251,9 +252,10 @@ function readableAddChunk(stream, chunk, encoding, addToFront) {
if (addToFront && state.encoding) {
// When unshifting, if state.encoding is set, we have to save
// the string in the BufferList with the state encoding.

chunk = Buffer.from(chunk, encoding).toString(state.encoding);
} else {
chunk = Buffer.from(chunk, encoding);
chunk = encodeWithFastPath(chunk, encoding);
encoding = '';
}
}
Expand Down
25 changes: 25 additions & 0 deletions lib/internal/streams/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ const {
Symbol,
SymbolAsyncIterator,
SymbolIterator,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetByteLength,
} = primordials;

const { normalizeEncoding } = require('internal/util');
const { FastBuffer } = require('internal/buffer');
const { TextEncoder } = require('internal/encoding');

const encoder = new TextEncoder();

const kDestroyed = Symbol('kDestroyed');
const kIsErrored = Symbol('kIsErrored');
const kIsReadable = Symbol('kIsReadable');
Expand Down Expand Up @@ -261,7 +270,23 @@ function isErrored(stream) {
));
}

function encodeWithFastPath(input, encoding) {
const enc = normalizeEncoding(encoding);

if (enc === 'utf8') {
const buf = encoder.encode(input);
return new FastBuffer(
TypedArrayPrototypeGetBuffer(buf),
TypedArrayPrototypeGetByteOffset(buf),
TypedArrayPrototypeGetByteLength(buf),
);
}

return Buffer.from(input, enc);
}

module.exports = {
encodeWithFastPath,
kDestroyed,
isDisturbed,
kIsDisturbed,
Expand Down

0 comments on commit 853ecc4

Please sign in to comment.