Skip to content

Commit 6512fd7

Browse files
mscdexaddaleax
authored andcommitted
stream: improve Transform performance
PR-URL: #13322 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent b22a04b commit 6512fd7

File tree

2 files changed

+53
-37
lines changed

2 files changed

+53
-37
lines changed
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
var common = require('../common.js');
3+
var Transform = require('stream').Transform;
4+
var inherits = require('util').inherits;
5+
6+
var bench = common.createBenchmark(main, {
7+
n: [1e6]
8+
});
9+
10+
function MyTransform() {
11+
Transform.call(this);
12+
}
13+
inherits(MyTransform, Transform);
14+
MyTransform.prototype._transform = function() {};
15+
16+
function main(conf) {
17+
var n = +conf.n;
18+
19+
bench.start();
20+
for (var i = 0; i < n; ++i)
21+
new MyTransform();
22+
bench.end(n);
23+
}

lib/_stream_transform.js

+30-37
Original file line numberDiff line numberDiff line change
@@ -70,41 +70,29 @@ const util = require('util');
7070
util.inherits(Transform, Duplex);
7171

7272

73-
function TransformState(stream) {
74-
this.afterTransform = function(er, data) {
75-
return afterTransform(stream, er, data);
76-
};
77-
78-
this.needTransform = false;
79-
this.transforming = false;
80-
this.writecb = null;
81-
this.writechunk = null;
82-
this.writeencoding = null;
83-
}
84-
85-
function afterTransform(stream, er, data) {
86-
var ts = stream._transformState;
73+
function afterTransform(er, data) {
74+
var ts = this._transformState;
8775
ts.transforming = false;
8876

8977
var cb = ts.writecb;
9078

9179
if (!cb) {
92-
return stream.emit('error',
93-
new Error('write callback called multiple times'));
80+
return this.emit('error',
81+
new Error('write callback called multiple times'));
9482
}
9583

9684
ts.writechunk = null;
9785
ts.writecb = null;
9886

99-
if (data !== null && data !== undefined)
100-
stream.push(data);
87+
if (data != null) // single equals check for both `null` and `undefined`
88+
this.push(data);
10189

10290
cb(er);
10391

104-
var rs = stream._readableState;
92+
var rs = this._readableState;
10593
rs.reading = false;
10694
if (rs.needReadable || rs.length < rs.highWaterMark) {
107-
stream._read(rs.highWaterMark);
95+
this._read(rs.highWaterMark);
10896
}
10997
}
11098

@@ -115,9 +103,14 @@ function Transform(options) {
115103

116104
Duplex.call(this, options);
117105

118-
this._transformState = new TransformState(this);
119-
120-
var stream = this;
106+
this._transformState = {
107+
afterTransform: afterTransform.bind(this),
108+
needTransform: false,
109+
transforming: false,
110+
writecb: null,
111+
writechunk: null,
112+
writeencoding: null
113+
};
121114

122115
// start out asking for a readable event once data is transformed.
123116
this._readableState.needReadable = true;
@@ -136,14 +129,17 @@ function Transform(options) {
136129
}
137130

138131
// When the writable side finishes, then flush out anything remaining.
139-
this.once('prefinish', function() {
140-
if (typeof this._flush === 'function')
141-
this._flush(function(er, data) {
142-
done(stream, er, data);
143-
});
144-
else
145-
done(stream);
146-
});
132+
this.on('prefinish', prefinish);
133+
}
134+
135+
function prefinish() {
136+
if (typeof this._flush === 'function') {
137+
this._flush((er, data) => {
138+
done(this, er, data);
139+
});
140+
} else {
141+
done(this, null, null);
142+
}
147143
}
148144

149145
Transform.prototype.push = function(chunk, encoding) {
@@ -208,18 +204,15 @@ function done(stream, er, data) {
208204
if (er)
209205
return stream.emit('error', er);
210206

211-
if (data !== null && data !== undefined)
207+
if (data != null) // single equals check for both `null` and `undefined`
212208
stream.push(data);
213209

214210
// if there's nothing in the write buffer, then that means
215211
// that nothing more will ever be provided
216-
var ws = stream._writableState;
217-
var ts = stream._transformState;
218-
219-
if (ws.length)
212+
if (stream._writableState.length)
220213
throw new Error('Calling transform done when ws.length != 0');
221214

222-
if (ts.transforming)
215+
if (stream._transformState.transforming)
223216
throw new Error('Calling transform done when still transforming');
224217

225218
return stream.push(null);

0 commit comments

Comments
 (0)