Skip to content

Commit 6ba37f5

Browse files
committed
stream: improve stream creation performance
1 parent 3662934 commit 6ba37f5

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
@@ -64,15 +64,16 @@ function prependListener(emitter, event, fn) {
6464
emitter._events[event] = [fn, emitter._events[event]];
6565
}
6666

67-
function ReadableState(options, stream) {
67+
function ReadableState(options, stream, isDuplex) {
6868
options = options || {};
6969

7070
// Duplex streams are both readable and writable, but share
7171
// the same options object.
7272
// However, some cases require setting options to different
7373
// values for the readable and the writable sides of the duplex stream.
7474
// These options can be provided separately as readableXXX and writableXXX.
75-
var isDuplex = stream instanceof Stream.Duplex;
75+
if (typeof isDuplex !== 'boolean')
76+
isDuplex = stream instanceof Stream.Duplex;
7677

7778
// object stream flag. Used to make read(n) ignore n and to
7879
// 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
@@ -48,15 +48,16 @@ util.inherits(Writable, Stream);
4848

4949
function nop() {}
5050

51-
function WritableState(options, stream) {
51+
function WritableState(options, stream, isDuplex) {
5252
options = options || {};
5353

5454
// Duplex streams are both readable and writable, but share
5555
// the same options object.
5656
// However, some cases require setting options to different
5757
// values for the readable and the writable sides of the duplex stream.
5858
// These options can be provided separately as readableXXX and writableXXX.
59-
var isDuplex = stream instanceof Stream.Duplex;
59+
if (typeof isDuplex !== 'boolean')
60+
isDuplex = stream instanceof Stream.Duplex;
6061

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

209-
this._writableState = new WritableState(options, this);
213+
this._writableState = new WritableState(options, this, isDuplex);
210214

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

0 commit comments

Comments
 (0)