From 62d9852c3d6ed32825abfd79645c72a66fb00e6f Mon Sep 17 00:00:00 2001 From: Tim Caswell Date: Mon, 12 Apr 2010 11:57:24 -0500 Subject: [PATCH] Replace slow and broken for..in loops with faster for loops over the keys. --- lib/child_process.js | 8 +++--- lib/dns.js | 19 ++++++++------ lib/fs.js | 16 ++++++++++-- lib/http.js | 60 ++++++++++++++++++++++++++++---------------- lib/ini.js | 37 +++++++++++++++++---------- lib/querystring.js | 18 ++++++++----- lib/url.js | 6 ++++- src/node.js | 8 ++++-- 8 files changed, 115 insertions(+), 57 deletions(-) diff --git a/lib/child_process.js b/lib/child_process.js index 4ed5a544a0..5a90442261 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -76,10 +76,10 @@ ChildProcess.prototype.spawn = function (path, args, env) { args = args || []; env = env || process.env; var envPairs = []; - for (var key in env) { - if (env.hasOwnProperty(key)) { - envPairs.push(key + "=" + env[key]); - } + var keys = Object.keys(env); + for (var index = 0, keysLength = keys.length; index < keysLength; index++) { + var key = keys[index]; + envPairs.push(key + "=" + env[key]); } var fds = this._internal.spawn(path, args, envPairs); diff --git a/lib/dns.js b/lib/dns.js index 6794ef426f..9bfca4752e 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -8,7 +8,9 @@ var activeWatchers = {}; var timer = new process.Timer(); timer.callback = function () { - for (var socket in activeWatchers) { + var sockets = Object.keys(activeWatchers); + for (var i = 0, l = sockets.length; i < l; i++) { + var socket = sockets[i]; var s = parseInt(socket); channel.processFD( watchers[socket].read ? s : dns.SOCKET_BAD , watchers[socket].write ? s : dns.SOCKET_BAD @@ -21,13 +23,16 @@ timer.callback = function () { function updateTimer() { timer.stop(); - for (var socket in activeWatchers) { // if !empty(activeWatchers) - var max = 20000; - var timeout = channel.timeout(max); - - timer.start(timeout, 0); + // Were just checking to see if activeWatchers is empty or not + for (var socket in activeWatchers) { + if (activeWatchers.hasOwnProperty(socket)) { + var max = 20000; + var timeout = channel.timeout(max); - return; + timer.start(timeout, 0); + // Short circuit the loop on first find. + return; + } } } diff --git a/lib/fs.js b/lib/fs.js index 4b2a4d120a..c3ab698e63 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -490,7 +490,13 @@ var FileReadStream = fs.FileReadStream = function(path, options) { this.bufferSize = 4 * 1024; options = options || {}; - for (var i in options) this[i] = options[i]; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } var self = this; @@ -621,7 +627,13 @@ var FileWriteStream = fs.FileWriteStream = function(path, options) { this.mode = 0666; options = options || {}; - for (var i in options) this[i] = options[i]; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } this.busy = false; this._queue = []; diff --git a/lib/http.js b/lib/http.js index 12130b68b6..717085396d 100644 --- a/lib/http.js +++ b/lib/http.js @@ -267,29 +267,34 @@ OutgoingMessage.prototype.sendHeaderLines = function (firstLine, headers) { // in the case of response it is: "HTTP/1.1 200 OK\r\n" var messageHeader = firstLine; var field, value; - for (var i in headers) { - if (headers[i] instanceof Array) { - field = headers[i][0]; - value = headers[i][1]; - } else { - if (!headers.hasOwnProperty(i)) continue; - field = i; - value = headers[i]; - } - messageHeader += field + ": " + value + CRLF; + if (headers) { + var keys = Object.keys(headers); + var isArray = (headers instanceof Array); + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + if (isArray) { + field = headers[key][0]; + value = headers[key][1]; + } else { + field = key; + value = headers[key]; + } + + messageHeader += field + ": " + value + CRLF; - if (connectionExpression.test(field)) { - sentConnectionHeader = true; - if (closeExpression.test(value)) this.closeOnFinish = true; + if (connectionExpression.test(field)) { + sentConnectionHeader = true; + if (closeExpression.test(value)) this.closeOnFinish = true; - } else if (transferEncodingExpression.test(field)) { - sentTransferEncodingHeader = true; - if (chunkExpression.test(value)) this.chunkedEncoding = true; + } else if (transferEncodingExpression.test(field)) { + sentTransferEncodingHeader = true; + if (chunkExpression.test(value)) this.chunkedEncoding = true; - } else if (contentLengthExpression.test(field)) { - sentContentLengthHeader = true; + } else if (contentLengthExpression.test(field)) { + sentContentLengthHeader = true; + } } } @@ -696,10 +701,21 @@ exports.cat = function (url, encoding_, headers_) { var url = require("url").parse(url); var hasHost = false; - for (var i in headers) { - if (i.toLowerCase() === "host") { - hasHost = true; - break; + if (headers instanceof Array) { + for (var i = 0, l = headers.length; i < l; i++) { + if (headers[i][0].toLowerCase() === 'host') { + hasHost = true; + break; + } + } + } else if (typeof headers === "Object") { + var keys = Object.keys(headers); + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + if (key.toLowerCase() == 'host') { + hasHost = true; + break; + } } } if (!hasHost) headers["Host"] = url.hostname; diff --git a/lib/ini.js b/lib/ini.js index 3a59457c60..ad309b719a 100644 --- a/lib/ini.js +++ b/lib/ini.js @@ -42,24 +42,35 @@ function safe (val) { return (val+"").replace(/[\n\r]+/g, " "); } +// ForEaches over an object. The only thing faster is to inline this function. +function objectEach(obj, fn, thisObj) { + var keys, key, i, length; + keys = Object.keys(obj); + length = keys.length; + for (i = 0; i < length; i++) { + key = keys[i]; + fn.call(thisObj, obj[key], key, obj); + } +} + exports.stringify = function (obj) { // if the obj has a "-" section, then do that first. - var ini = ""; + var ini = []; if ("-" in obj) { - for (var key in obj["-"]) { - ini += safe(key)+" = "+safe(obj["-"][key])+"\n"; - } + objectEach(obj["-"], function (value, key) { + ini[ini.length] = safe(key) + " = " + safe(value) + "\n"; + }); } - for (var section in obj) if (section !== "-") { - ini += "[" + safe(section) + "]\n"; - for (var key in obj[section]) { - - ini += safe(key) + ((obj[section][key] === true) + objectEach(obj, function (section, name) { + if (name === "-") return; + ini[ini.length] = "[" + safe(name) + "]\n"; + objectEach(section, function (value, key) { + ini[ini.length] = safe(key) + ((value === true) ? "\n" - : " = "+safe(obj[section][key])+"\n"); - } - } - return ini; + : " = "+safe(value)+"\n"); + }); + }); + return ini.join(""); }; exports.encode = exports.stringify; diff --git a/lib/querystring.js b/lib/querystring.js index 5220b53ae9..83e0a0f85e 100644 --- a/lib/querystring.js +++ b/lib/querystring.js @@ -55,9 +55,11 @@ QueryString.stringify = function (obj, sep, eq, name) { var s = []; var begin = name ? name + '[' : ''; var end = name ? ']' : ''; - for (var i in obj) if (obj.hasOwnProperty(i)) { - var n = begin + i + end; - s.push(QueryString.stringify(obj[i], sep, eq, n)); + var keys = Object.keys(obj); + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + var n = begin + key + end; + s.push(QueryString.stringify(obj[key], sep, eq, n)); } stack.pop(); @@ -138,10 +140,14 @@ function mergeParams (params, addition) { }; // Merge two *objects* together. If this is called, we've already ruled -// out the simple cases, and need to do the for-in business. +// out the simple cases, and need to do a loop. function mergeObjects (params, addition) { - for (var i in addition) if (i && addition.hasOwnProperty(i)) { - params[i] = mergeParams(params[i], addition[i]); + var keys = Object.keys(addition); + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + if (key) { + params[key] = mergeParams(params[key], addition[key]); + } } return params; }; diff --git a/lib/url.js b/lib/url.js index e6f2d71ebe..c4b534a5d5 100644 --- a/lib/url.js +++ b/lib/url.js @@ -56,7 +56,11 @@ function urlParse (url, parseQueryString) { // pull out the auth and port. var p = parseHost(out.host); - for (var i in p) out[i] = p[i]; + var keys = Object.keys(p); + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + out[key] = p[key]; + } // we've indicated that there is a hostname, so even if it's empty, it has to be present. out.hostname = out.hostname || ""; } diff --git a/src/node.js b/src/node.js index 675e3bc048..eb703d93c7 100644 --- a/src/node.js +++ b/src/node.js @@ -462,7 +462,9 @@ function findModulePath (id, dirs, callback) { ]; var ext; - for (ext in extensionCache) { + var extensions = Object.keys(extensionCache); + for (var i = 0, l = extensions.length; i < l; i++) { + var ext = extensions[i]; locations.push(path.join(dir, id + ext)); locations.push(path.join(dir, id, 'index' + ext)); } @@ -504,7 +506,9 @@ function resolveModulePath(request, parent) { debug("RELATIVE: requested:" + request + " set ID to: "+id+" from "+parent.id); var exts = ['js', 'node'], ext; - for (ext in extensionCache) { + var extensions = Object.keys(extensionCache); + for (var i = 0, l = extensions.length; i < l; i++) { + var ext = extensions[i]; exts.push(ext.slice(1)); }