Skip to content

Commit f13cc32

Browse files
mscdextargos
authored andcommitted
stream: improve stream creation performance
PR-URL: #19401 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Minwoo Jung <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]>
1 parent 6591d9f commit f13cc32

File tree

4 files changed

+73
-30
lines changed

4 files changed

+73
-30
lines changed

benchmark/streams/creation.js

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict';
2+
const common = require('../common.js');
3+
const Duplex = require('stream').Duplex;
4+
const Readable = require('stream').Readable;
5+
const Transform = require('stream').Transform;
6+
const Writable = require('stream').Writable;
7+
8+
const bench = common.createBenchmark(main, {
9+
n: [50e6],
10+
kind: ['duplex', 'readable', 'transform', 'writable']
11+
});
12+
13+
function main({ n, kind }) {
14+
var i = 0;
15+
switch (kind) {
16+
case 'duplex':
17+
new Duplex({});
18+
new Duplex();
19+
20+
bench.start();
21+
for (; i < n; ++i)
22+
new Duplex();
23+
bench.end(n);
24+
break;
25+
case 'readable':
26+
new Readable({});
27+
new Readable();
28+
29+
bench.start();
30+
for (; i < n; ++i)
31+
new Readable();
32+
bench.end(n);
33+
break;
34+
case 'writable':
35+
new Writable({});
36+
new Writable();
37+
38+
bench.start();
39+
for (; i < n; ++i)
40+
new Writable();
41+
bench.end(n);
42+
break;
43+
case 'transform':
44+
new Transform({});
45+
new Transform();
46+
47+
bench.start();
48+
for (; i < n; ++i)
49+
new Transform();
50+
bench.end(n);
51+
break;
52+
default:
53+
throw new Error('Invalid kind');
54+
}
55+
}

benchmark/streams/transform-creation.js

-21
This file was deleted.

lib/_stream_readable.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,16 @@ function prependListener(emitter, event, fn) {
5656
emitter._events[event] = [fn, emitter._events[event]];
5757
}
5858

59-
function ReadableState(options, stream) {
59+
function ReadableState(options, stream, isDuplex) {
6060
options = options || {};
6161

6262
// Duplex streams are both readable and writable, but share
6363
// the same options object.
6464
// However, some cases require setting options to different
6565
// values for the readable and the writable sides of the duplex stream.
6666
// These options can be provided separately as readableXXX and writableXXX.
67-
var isDuplex = stream instanceof Stream.Duplex;
67+
if (typeof isDuplex !== 'boolean')
68+
isDuplex = stream instanceof Stream.Duplex;
6869

6970
// object stream flag. Used to make read(n) ignore n and to
7071
// make all the buffer merging and length checks go away
@@ -142,7 +143,11 @@ function Readable(options) {
142143
if (!(this instanceof Readable))
143144
return new Readable(options);
144145

145-
this._readableState = new ReadableState(options, this);
146+
// Checking for a Stream.Duplex instance is faster here instead of inside
147+
// the ReadableState constructor, at least with V8 6.5
148+
const isDuplex = (this instanceof Stream.Duplex);
149+
150+
this._readableState = new ReadableState(options, this, isDuplex);
146151

147152
// legacy
148153
this.readable = true;

lib/_stream_writable.js

+10-6
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,16 @@ util.inherits(Writable, Stream);
3939

4040
function nop() {}
4141

42-
function WritableState(options, stream) {
42+
function WritableState(options, stream, isDuplex) {
4343
options = options || {};
4444

4545
// Duplex streams are both readable and writable, but share
4646
// the same options object.
4747
// However, some cases require setting options to different
4848
// values for the readable and the writable sides of the duplex stream.
4949
// These options can be provided separately as readableXXX and writableXXX.
50-
var isDuplex = stream instanceof Stream.Duplex;
50+
if (typeof isDuplex !== 'boolean')
51+
isDuplex = stream instanceof Stream.Duplex;
5152

5253
// object stream flag to indicate whether or not this stream
5354
// contains buffers or objects.
@@ -200,12 +201,15 @@ function Writable(options) {
200201
// Trying to use the custom `instanceof` for Writable here will also break the
201202
// Node.js LazyTransform implementation, which has a non-trivial getter for
202203
// `_writableState` that would lead to infinite recursion.
203-
if (!(realHasInstance.call(Writable, this)) &&
204-
!(this instanceof Stream.Duplex)) {
204+
205+
// Checking for a Stream.Duplex instance is faster here instead of inside
206+
// the WritableState constructor, at least with V8 6.5
207+
const isDuplex = (this instanceof Stream.Duplex);
208+
209+
if (!isDuplex && !realHasInstance.call(Writable, this))
205210
return new Writable(options);
206-
}
207211

208-
this._writableState = new WritableState(options, this);
212+
this._writableState = new WritableState(options, this, isDuplex);
209213

210214
// legacy.
211215
this.writable = true;

0 commit comments

Comments
 (0)