From: Brendan Ashworth Date: Tue, 7 Apr 2015 08:37:13 +0000 (-0700) Subject: lib: reduce process.binding() calls X-Git-Tag: v1.7.0~22 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1219e7466cddf705d340ef566f6c1958f75735bb;p=platform%2Fupstream%2Fnodejs.git 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: https://github.com/iojs/io.js/pull/1367 Reviewed-By: Brian White Reviewed-By: Ben Noordhuis --- diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index fcc216b..3e091b0 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -12,18 +12,8 @@ const Duplex = require('stream').Duplex; const debug = util.debuglog('tls'); const Timer = process.binding('timer_wrap').Timer; const tls_wrap = process.binding('tls_wrap'); - -// constructor for lazy loading -function createTCP() { - var TCP = process.binding('tcp_wrap').TCP; - return new TCP(); -} - -// constructor for lazy loading -function createPipe() { - var Pipe = process.binding('pipe_wrap').Pipe; - return new Pipe(); -} +const TCP = process.binding('tcp_wrap').TCP; +const Pipe = process.binding('pipe_wrap').Pipe; function onhandshakestart() { debug('onhandshakestart'); @@ -284,7 +274,7 @@ TLSSocket.prototype._wrapHandle = function(handle) { var options = this._tlsOptions; if (!handle) { - handle = options.pipe ? createPipe() : createTCP(); + handle = options.pipe ? new Pipe() : new TCP(); handle.owner = this; } diff --git a/lib/child_process.js b/lib/child_process.js index a38de28..0fdbcf4 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -7,48 +7,18 @@ const dgram = require('dgram'); const assert = require('assert'); const util = require('util'); const debug = util.debuglog('child_process'); +const constants = require('constants'); const Process = process.binding('process_wrap').Process; const WriteWrap = process.binding('stream_wrap').WriteWrap; const uv = process.binding('uv'); - -var spawn_sync; // Lazy-loaded process.binding('spawn_sync') -var constants; // Lazy-loaded process.binding('constants') +const spawn_sync = process.binding('spawn_sync'); +const Pipe = process.binding('pipe_wrap').Pipe; +const TTY = process.binding('tty_wrap').TTY; +const TCP = process.binding('tcp_wrap').TCP; +const UDP = process.binding('udp_wrap').UDP; const errnoException = util._errnoException; -var handleWraps = {}; - -function handleWrapGetter(name, callback) { - var cons; - - Object.defineProperty(handleWraps, name, { - get: function() { - if (cons !== undefined) return cons; - return cons = callback(); - } - }); -} - -handleWrapGetter('Pipe', function() { - return process.binding('pipe_wrap').Pipe; -}); - -handleWrapGetter('TTY', function() { - return process.binding('tty_wrap').TTY; -}); - -handleWrapGetter('TCP', function() { - return process.binding('tcp_wrap').TCP; -}); - -handleWrapGetter('UDP', function() { - return process.binding('udp_wrap').UDP; -}); - -// constructors for lazy loading -function createPipe(ipc) { - return new handleWraps.Pipe(ipc); -} function createSocket(pipe, readable) { var s = new net.Socket({ handle: pipe }); @@ -417,12 +387,11 @@ function setupChannel(target, channel) { message.type = 'net.Socket'; } else if (handle instanceof net.Server) { message.type = 'net.Server'; - } else if (handle instanceof process.binding('tcp_wrap').TCP || - handle instanceof process.binding('pipe_wrap').Pipe) { + } else if (handle instanceof TCP || handle instanceof Pipe) { message.type = 'net.Native'; } else if (handle instanceof dgram.Socket) { message.type = 'dgram.Socket'; - } else if (handle instanceof process.binding('udp_wrap').UDP) { + } else if (handle instanceof UDP) { message.type = 'dgram.Native'; } else { throw new TypeError("This handle type can't be sent"); @@ -564,7 +533,7 @@ exports.fork = function(modulePath /*, args, options*/) { exports._forkChild = function(fd) { // set process.send() - var p = createPipe(true); + var p = new Pipe(true); p.open(fd); p.unref(); setupChannel(process, p); @@ -852,7 +821,7 @@ function _validateStdio(stdio, sync) { }; if (!sync) - a.handle = createPipe(); + a.handle = new Pipe(); acc.push(a); } else if (stdio === 'ipc') { @@ -865,7 +834,7 @@ function _validateStdio(stdio, sync) { throw new Error('You cannot use IPC with synchronous forks'); } - ipc = createPipe(true); + ipc = new Pipe(true); ipcFd = i; acc.push({ @@ -989,10 +958,6 @@ function maybeClose(subprocess) { function ChildProcess() { EventEmitter.call(this); - // Initialize TCPWrap and PipeWrap - process.binding('tcp_wrap'); - process.binding('pipe_wrap'); - var self = this; this._closesNeeded = 1; @@ -1072,10 +1037,10 @@ function flushStdio(subprocess) { function getHandleWrapType(stream) { - if (stream instanceof handleWraps.Pipe) return 'pipe'; - if (stream instanceof handleWraps.TTY) return 'tty'; - if (stream instanceof handleWraps.TCP) return 'tcp'; - if (stream instanceof handleWraps.UDP) return 'udp'; + if (stream instanceof Pipe) return 'pipe'; + if (stream instanceof TTY) return 'tty'; + if (stream instanceof TCP) return 'tcp'; + if (stream instanceof UDP) return 'udp'; return false; } @@ -1177,10 +1142,6 @@ ChildProcess.prototype.spawn = function(options) { ChildProcess.prototype.kill = function(sig) { var signal; - if (!constants) { - constants = process.binding('constants'); - } - if (sig === 0) { signal = 0; } else if (!sig) { @@ -1230,9 +1191,6 @@ function lookupSignal(signal) { if (typeof signal === 'number') return signal; - if (!constants) - constants = process.binding('constants'); - if (!(signal in constants)) throw new Error('Unknown signal: ' + signal); @@ -1280,9 +1238,6 @@ function spawnSync(/*file, args, options*/) { } } - if (!spawn_sync) - spawn_sync = process.binding('spawn_sync'); - var result = spawn_sync.spawn(options); if (result.output && options.encoding) { diff --git a/lib/cluster.js b/lib/cluster.js index 14d0bc6..08230ad 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -9,6 +9,8 @@ const util = require('util'); const SCHED_NONE = 1; const SCHED_RR = 2; +const uv = process.binding('uv'); + const cluster = new EventEmitter; module.exports = cluster; cluster.Worker = Worker; @@ -142,7 +144,7 @@ RoundRobinHandle.prototype.add = function(worker, send) { // Hack: translate 'EADDRINUSE' error string back to numeric error code. // It works but ideally we'd have some backchannel between the net and // cluster modules for stuff like this. - var errno = process.binding('uv')['UV_' + err.errno]; + var errno = uv['UV_' + err.errno]; send(errno, null); }); }; diff --git a/lib/dgram.js b/lib/dgram.js index f005b88..4708f4d 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -146,7 +146,6 @@ Socket.prototype.bind = function(port /*, address, callback*/) { if (typeof arguments[arguments.length - 1] === 'function') self.once('listening', arguments[arguments.length - 1]); - const UDP = process.binding('udp_wrap').UDP; if (port instanceof UDP) { replaceHandle(self, port); startListening(self); diff --git a/lib/fs.js b/lib/fs.js index 472d03c..0025e6a 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -8,11 +8,12 @@ const util = require('util'); const pathModule = require('path'); const binding = process.binding('fs'); -const constants = process.binding('constants'); +const constants = require('constants'); const fs = exports; const Stream = require('stream').Stream; const EventEmitter = require('events').EventEmitter; const FSReqWrap = binding.FSReqWrap; +const FSEvent = process.binding('fs_event_wrap').FSEvent; const Readable = Stream.Readable; const Writable = Stream.Writable; @@ -1201,7 +1202,6 @@ function FSWatcher() { EventEmitter.call(this); var self = this; - var FSEvent = process.binding('fs_event_wrap').FSEvent; this._handle = new FSEvent(); this._handle.owner = this; diff --git a/lib/net.js b/lib/net.js index 9aca392..ac6acd6 100644 --- a/lib/net.js +++ b/lib/net.js @@ -7,8 +7,10 @@ const util = require('util'); const assert = require('assert'); const cares = process.binding('cares_wrap'); const uv = process.binding('uv'); -const Pipe = process.binding('pipe_wrap').Pipe; +const TTYWrap = process.binding('tty_wrap'); +const TCP = process.binding('tcp_wrap').TCP; +const Pipe = process.binding('pipe_wrap').Pipe; const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap; const PipeConnectWrap = process.binding('pipe_wrap').PipeConnectWrap; const ShutdownWrap = process.binding('stream_wrap').ShutdownWrap; @@ -21,23 +23,10 @@ const exceptionWithHostPort = util._exceptionWithHostPort; function noop() {} -// constructor for lazy loading -function createPipe() { - return new Pipe(); -} - -// constructor for lazy loading -function createTCP() { - var TCP = process.binding('tcp_wrap').TCP; - return new TCP(); -} - - function createHandle(fd) { - var tty = process.binding('tty_wrap'); - var type = tty.guessHandleType(fd); - if (type === 'PIPE') return createPipe(); - if (type === 'TCP') return createTCP(); + var type = TTYWrap.guessHandleType(fd); + if (type === 'PIPE') return new Pipe(); + if (type === 'TCP') return new TCP(); throw new TypeError('Unsupported fd type: ' + type); } @@ -873,7 +862,7 @@ Socket.prototype.connect = function(options, cb) { debug('pipe', pipe, options.path); if (!this._handle) { - this._handle = pipe ? createPipe() : createTCP(); + this._handle = pipe ? new Pipe() : new TCP(); initSocketHandle(this); } @@ -1095,7 +1084,7 @@ var createServerHandle = exports._createServerHandle = handle.writable = true; assert(!address && !port); } else if (port === -1 && addressType === -1) { - handle = createPipe(); + handle = new Pipe(); if (process.platform === 'win32') { var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES); if (!isNaN(instances)) { @@ -1103,7 +1092,7 @@ var createServerHandle = exports._createServerHandle = } } } else { - handle = createTCP(); + handle = new TCP(); isTCP = true; } @@ -1255,8 +1244,6 @@ Server.prototype.listen = function() { // When the ip is omitted it can be the second argument. var backlog = toNumber(arguments[1]) || toNumber(arguments[2]); - const TCP = process.binding('tcp_wrap').TCP; - if (arguments.length === 0 || typeof arguments[0] === 'function') { // Bind to a random port. listen(self, null, 0, null, backlog); diff --git a/lib/tls.js b/lib/tls.js index 9e1b928..3ae7a8f 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -3,6 +3,7 @@ const net = require('net'); const url = require('url'); const util = require('util'); +const binding = process.binding('crypto'); // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more @@ -35,7 +36,7 @@ exports.DEFAULT_CIPHERS = [ exports.DEFAULT_ECDH_CURVE = 'prime256v1'; exports.getCiphers = function() { - const names = process.binding('crypto').getSSLCiphers(); + const names = binding.getSSLCiphers(); // Drop all-caps names in favor of their lowercase aliases, var ctx = {}; names.forEach(function(name) { diff --git a/lib/util.js b/lib/util.js index 39f521f..a04c19c 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,5 +1,7 @@ 'use strict'; +const uv = process.binding('uv'); + const formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (typeof f !== 'string') { @@ -739,9 +741,7 @@ exports.pump = exports.deprecate(function(readStream, writeStream, callback) { }, 'util.pump(): Use readableStream.pipe() instead'); -var uv; exports._errnoException = function(err, syscall, original) { - if (uv === undefined) uv = process.binding('uv'); var errname = uv.errname(err); var message = syscall + ' ' + errname; if (original)