Skip to content

Commit 1219e74

Browse files
lib: reduce process.binding() calls
This commit better handles calls to process.binding() in lib/ by no longer lazy loading the bindings (the load times themselves are rather miniscule compared to the load time of V8) and never reloading the bindings (which is 172 times slower than referencing a variable with the same value). PR-URL: #1367 Reviewed-By: Brian White <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 69bc138 commit 1219e74

File tree

8 files changed

+36
-102
lines changed

8 files changed

+36
-102
lines changed

lib/_tls_wrap.js

+3-13
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,8 @@ const Duplex = require('stream').Duplex;
1212
const debug = util.debuglog('tls');
1313
const Timer = process.binding('timer_wrap').Timer;
1414
const tls_wrap = process.binding('tls_wrap');
15-
16-
// constructor for lazy loading
17-
function createTCP() {
18-
var TCP = process.binding('tcp_wrap').TCP;
19-
return new TCP();
20-
}
21-
22-
// constructor for lazy loading
23-
function createPipe() {
24-
var Pipe = process.binding('pipe_wrap').Pipe;
25-
return new Pipe();
26-
}
15+
const TCP = process.binding('tcp_wrap').TCP;
16+
const Pipe = process.binding('pipe_wrap').Pipe;
2717

2818
function onhandshakestart() {
2919
debug('onhandshakestart');
@@ -284,7 +274,7 @@ TLSSocket.prototype._wrapHandle = function(handle) {
284274

285275
var options = this._tlsOptions;
286276
if (!handle) {
287-
handle = options.pipe ? createPipe() : createTCP();
277+
handle = options.pipe ? new Pipe() : new TCP();
288278
handle.owner = this;
289279
}
290280

lib/child_process.js

+15-60
Original file line numberDiff line numberDiff line change
@@ -7,48 +7,18 @@ const dgram = require('dgram');
77
const assert = require('assert');
88
const util = require('util');
99
const debug = util.debuglog('child_process');
10+
const constants = require('constants');
1011

1112
const Process = process.binding('process_wrap').Process;
1213
const WriteWrap = process.binding('stream_wrap').WriteWrap;
1314
const uv = process.binding('uv');
14-
15-
var spawn_sync; // Lazy-loaded process.binding('spawn_sync')
16-
var constants; // Lazy-loaded process.binding('constants')
15+
const spawn_sync = process.binding('spawn_sync');
16+
const Pipe = process.binding('pipe_wrap').Pipe;
17+
const TTY = process.binding('tty_wrap').TTY;
18+
const TCP = process.binding('tcp_wrap').TCP;
19+
const UDP = process.binding('udp_wrap').UDP;
1720

1821
const errnoException = util._errnoException;
19-
var handleWraps = {};
20-
21-
function handleWrapGetter(name, callback) {
22-
var cons;
23-
24-
Object.defineProperty(handleWraps, name, {
25-
get: function() {
26-
if (cons !== undefined) return cons;
27-
return cons = callback();
28-
}
29-
});
30-
}
31-
32-
handleWrapGetter('Pipe', function() {
33-
return process.binding('pipe_wrap').Pipe;
34-
});
35-
36-
handleWrapGetter('TTY', function() {
37-
return process.binding('tty_wrap').TTY;
38-
});
39-
40-
handleWrapGetter('TCP', function() {
41-
return process.binding('tcp_wrap').TCP;
42-
});
43-
44-
handleWrapGetter('UDP', function() {
45-
return process.binding('udp_wrap').UDP;
46-
});
47-
48-
// constructors for lazy loading
49-
function createPipe(ipc) {
50-
return new handleWraps.Pipe(ipc);
51-
}
5222

5323
function createSocket(pipe, readable) {
5424
var s = new net.Socket({ handle: pipe });
@@ -417,12 +387,11 @@ function setupChannel(target, channel) {
417387
message.type = 'net.Socket';
418388
} else if (handle instanceof net.Server) {
419389
message.type = 'net.Server';
420-
} else if (handle instanceof process.binding('tcp_wrap').TCP ||
421-
handle instanceof process.binding('pipe_wrap').Pipe) {
390+
} else if (handle instanceof TCP || handle instanceof Pipe) {
422391
message.type = 'net.Native';
423392
} else if (handle instanceof dgram.Socket) {
424393
message.type = 'dgram.Socket';
425-
} else if (handle instanceof process.binding('udp_wrap').UDP) {
394+
} else if (handle instanceof UDP) {
426395
message.type = 'dgram.Native';
427396
} else {
428397
throw new TypeError("This handle type can't be sent");
@@ -564,7 +533,7 @@ exports.fork = function(modulePath /*, args, options*/) {
564533

565534
exports._forkChild = function(fd) {
566535
// set process.send()
567-
var p = createPipe(true);
536+
var p = new Pipe(true);
568537
p.open(fd);
569538
p.unref();
570539
setupChannel(process, p);
@@ -852,7 +821,7 @@ function _validateStdio(stdio, sync) {
852821
};
853822

854823
if (!sync)
855-
a.handle = createPipe();
824+
a.handle = new Pipe();
856825

857826
acc.push(a);
858827
} else if (stdio === 'ipc') {
@@ -865,7 +834,7 @@ function _validateStdio(stdio, sync) {
865834
throw new Error('You cannot use IPC with synchronous forks');
866835
}
867836

868-
ipc = createPipe(true);
837+
ipc = new Pipe(true);
869838
ipcFd = i;
870839

871840
acc.push({
@@ -989,10 +958,6 @@ function maybeClose(subprocess) {
989958
function ChildProcess() {
990959
EventEmitter.call(this);
991960

992-
// Initialize TCPWrap and PipeWrap
993-
process.binding('tcp_wrap');
994-
process.binding('pipe_wrap');
995-
996961
var self = this;
997962

998963
this._closesNeeded = 1;
@@ -1072,10 +1037,10 @@ function flushStdio(subprocess) {
10721037

10731038

10741039
function getHandleWrapType(stream) {
1075-
if (stream instanceof handleWraps.Pipe) return 'pipe';
1076-
if (stream instanceof handleWraps.TTY) return 'tty';
1077-
if (stream instanceof handleWraps.TCP) return 'tcp';
1078-
if (stream instanceof handleWraps.UDP) return 'udp';
1040+
if (stream instanceof Pipe) return 'pipe';
1041+
if (stream instanceof TTY) return 'tty';
1042+
if (stream instanceof TCP) return 'tcp';
1043+
if (stream instanceof UDP) return 'udp';
10791044

10801045
return false;
10811046
}
@@ -1177,10 +1142,6 @@ ChildProcess.prototype.spawn = function(options) {
11771142
ChildProcess.prototype.kill = function(sig) {
11781143
var signal;
11791144

1180-
if (!constants) {
1181-
constants = process.binding('constants');
1182-
}
1183-
11841145
if (sig === 0) {
11851146
signal = 0;
11861147
} else if (!sig) {
@@ -1230,9 +1191,6 @@ function lookupSignal(signal) {
12301191
if (typeof signal === 'number')
12311192
return signal;
12321193

1233-
if (!constants)
1234-
constants = process.binding('constants');
1235-
12361194
if (!(signal in constants))
12371195
throw new Error('Unknown signal: ' + signal);
12381196

@@ -1280,9 +1238,6 @@ function spawnSync(/*file, args, options*/) {
12801238
}
12811239
}
12821240

1283-
if (!spawn_sync)
1284-
spawn_sync = process.binding('spawn_sync');
1285-
12861241
var result = spawn_sync.spawn(options);
12871242

12881243
if (result.output && options.encoding) {

lib/cluster.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const util = require('util');
99
const SCHED_NONE = 1;
1010
const SCHED_RR = 2;
1111

12+
const uv = process.binding('uv');
13+
1214
const cluster = new EventEmitter;
1315
module.exports = cluster;
1416
cluster.Worker = Worker;
@@ -142,7 +144,7 @@ RoundRobinHandle.prototype.add = function(worker, send) {
142144
// Hack: translate 'EADDRINUSE' error string back to numeric error code.
143145
// It works but ideally we'd have some backchannel between the net and
144146
// cluster modules for stuff like this.
145-
var errno = process.binding('uv')['UV_' + err.errno];
147+
var errno = uv['UV_' + err.errno];
146148
send(errno, null);
147149
});
148150
};

lib/dgram.js

-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ Socket.prototype.bind = function(port /*, address, callback*/) {
146146
if (typeof arguments[arguments.length - 1] === 'function')
147147
self.once('listening', arguments[arguments.length - 1]);
148148

149-
const UDP = process.binding('udp_wrap').UDP;
150149
if (port instanceof UDP) {
151150
replaceHandle(self, port);
152151
startListening(self);

lib/fs.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ const util = require('util');
88
const pathModule = require('path');
99

1010
const binding = process.binding('fs');
11-
const constants = process.binding('constants');
11+
const constants = require('constants');
1212
const fs = exports;
1313
const Stream = require('stream').Stream;
1414
const EventEmitter = require('events').EventEmitter;
1515
const FSReqWrap = binding.FSReqWrap;
16+
const FSEvent = process.binding('fs_event_wrap').FSEvent;
1617

1718
const Readable = Stream.Readable;
1819
const Writable = Stream.Writable;
@@ -1201,7 +1202,6 @@ function FSWatcher() {
12011202
EventEmitter.call(this);
12021203

12031204
var self = this;
1204-
var FSEvent = process.binding('fs_event_wrap').FSEvent;
12051205
this._handle = new FSEvent();
12061206
this._handle.owner = this;
12071207

lib/net.js

+9-22
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ const util = require('util');
77
const assert = require('assert');
88
const cares = process.binding('cares_wrap');
99
const uv = process.binding('uv');
10-
const Pipe = process.binding('pipe_wrap').Pipe;
1110

11+
const TTYWrap = process.binding('tty_wrap');
12+
const TCP = process.binding('tcp_wrap').TCP;
13+
const Pipe = process.binding('pipe_wrap').Pipe;
1214
const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap;
1315
const PipeConnectWrap = process.binding('pipe_wrap').PipeConnectWrap;
1416
const ShutdownWrap = process.binding('stream_wrap').ShutdownWrap;
@@ -21,23 +23,10 @@ const exceptionWithHostPort = util._exceptionWithHostPort;
2123

2224
function noop() {}
2325

24-
// constructor for lazy loading
25-
function createPipe() {
26-
return new Pipe();
27-
}
28-
29-
// constructor for lazy loading
30-
function createTCP() {
31-
var TCP = process.binding('tcp_wrap').TCP;
32-
return new TCP();
33-
}
34-
35-
3626
function createHandle(fd) {
37-
var tty = process.binding('tty_wrap');
38-
var type = tty.guessHandleType(fd);
39-
if (type === 'PIPE') return createPipe();
40-
if (type === 'TCP') return createTCP();
27+
var type = TTYWrap.guessHandleType(fd);
28+
if (type === 'PIPE') return new Pipe();
29+
if (type === 'TCP') return new TCP();
4130
throw new TypeError('Unsupported fd type: ' + type);
4231
}
4332

@@ -873,7 +862,7 @@ Socket.prototype.connect = function(options, cb) {
873862
debug('pipe', pipe, options.path);
874863

875864
if (!this._handle) {
876-
this._handle = pipe ? createPipe() : createTCP();
865+
this._handle = pipe ? new Pipe() : new TCP();
877866
initSocketHandle(this);
878867
}
879868

@@ -1095,15 +1084,15 @@ var createServerHandle = exports._createServerHandle =
10951084
handle.writable = true;
10961085
assert(!address && !port);
10971086
} else if (port === -1 && addressType === -1) {
1098-
handle = createPipe();
1087+
handle = new Pipe();
10991088
if (process.platform === 'win32') {
11001089
var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES);
11011090
if (!isNaN(instances)) {
11021091
handle.setPendingInstances(instances);
11031092
}
11041093
}
11051094
} else {
1106-
handle = createTCP();
1095+
handle = new TCP();
11071096
isTCP = true;
11081097
}
11091098

@@ -1255,8 +1244,6 @@ Server.prototype.listen = function() {
12551244
// When the ip is omitted it can be the second argument.
12561245
var backlog = toNumber(arguments[1]) || toNumber(arguments[2]);
12571246

1258-
const TCP = process.binding('tcp_wrap').TCP;
1259-
12601247
if (arguments.length === 0 || typeof arguments[0] === 'function') {
12611248
// Bind to a random port.
12621249
listen(self, null, 0, null, backlog);

lib/tls.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const net = require('net');
44
const url = require('url');
55
const util = require('util');
6+
const binding = process.binding('crypto');
67

78
// Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations
89
// every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more
@@ -35,7 +36,7 @@ exports.DEFAULT_CIPHERS = [
3536
exports.DEFAULT_ECDH_CURVE = 'prime256v1';
3637

3738
exports.getCiphers = function() {
38-
const names = process.binding('crypto').getSSLCiphers();
39+
const names = binding.getSSLCiphers();
3940
// Drop all-caps names in favor of their lowercase aliases,
4041
var ctx = {};
4142
names.forEach(function(name) {

lib/util.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const uv = process.binding('uv');
4+
35
const formatRegExp = /%[sdj%]/g;
46
exports.format = function(f) {
57
if (typeof f !== 'string') {
@@ -739,9 +741,7 @@ exports.pump = exports.deprecate(function(readStream, writeStream, callback) {
739741
}, 'util.pump(): Use readableStream.pipe() instead');
740742

741743

742-
var uv;
743744
exports._errnoException = function(err, syscall, original) {
744-
if (uv === undefined) uv = process.binding('uv');
745745
var errname = uv.errname(err);
746746
var message = syscall + ' ' + errname;
747747
if (original)

0 commit comments

Comments
 (0)