I am noticing a significant difference in speed between plain node.js VS node-webkit
All I'm doing is connecting to a localhost couchdb using the HTTP module.
The same code takes ~520ms to establish a connection and return a response in node-webkit whereas it takes ~10ms in plain node.js
Can someone with more in-depth knowledge of node-webkit help explain what is causing this?
The code is below
Class = new function() {};
Class.prototype.info = function(s) {console.log(console,s);}
Class.prototype.err = function(s) {console.log(console,s);}
Class.prototype.warning = function(s) {console.log(console,s);}
Class.prototype.debug = function(s) {console.log(console,s);}
Class.prototype.postMessage = function(oterm, msg) {
__cb.shift().call(this, msg);
}
Class.prototype.onMsgFor = {};
Class.prototype.__agentkeepalive = require('agentkeepalive');
Class.prototype.__http = require("http");
Class.prototype.__follow = require("follow");
Class.prototype.__http.globalAgent.maxSockets = 1;
Class.prototype._onInit = function(props) {
this._host = props["host"];
this._port = props["port"];
this._db_name = props["name"];
this._agent = new this.__agentkeepalive({
minSockets: 1
,maxSockets: 1
, maxKeepAliveRequests: 0
, maxKeepAliveTime: 300000
});
};
Class.prototype.onMsgFor["connect_request_in"] = function(msg) {
var err;
var self = this;
self._connect(this._host, this._port, this._db_name);
};
/*************************************************************************/
Class.prototype._connect = function(host, port, namespace) {
var self = this;
var err;
function _onConnect(code, body, hdrs) {
function _onCreate(code, body, hdrs) {
if (code == 201) { // created
//self._registerChangeNotification();
self.postMessage("connect_response_out", {name: namespace});
} else {
alert(code);
err = "Unable to create namespace: " + namespace;
self.error(err);
self.postMessage("error_response_out", {text_content:err});
}
}
if (code == undefined) { // no code means error connecting
self.error("Error connecting to DB: " + body);
self.postMessage("error_response_out", {text_content:body
,question: "Is CouchDB up?"});
} else if (code == 200) { // ok
if (body.indexOf(namespace) != -1) {
//self._registerChangeNotification();
self.postMessage("connect_response_out", {name: namespace});
} else {
self.warning("No such namespace: " + namespace);
self._request(host, port, namespace, "PUT", _onCreate);
}
} else {
alert("Unexpected code: " + code);
}
return;
}
self._request( host, port, "_all_dbs", "GET", _onConnect);
};
Class.prototype._request = function(host, port, namespace, method, cb, uuid, arg, opts) {
var t = (new Date()).getTime();
var self = this;
var path = "/" + escape(namespace) + (uuid ? ("/" + escape(uuid)) : "");
var req, k, buf = "", headers = {};
if (method == "POST" || method == "PUT") {
headers["content-type"] = "application/json";
buf = JSON.stringify(arg);
}
if (opts) {
path += "?";
for (k in opts) {
path += k + "=" + opts[k];
}
}
self.info("http://" + host + ":" + port + path);
req = this.__http.request({hostname: host
, port: port
, path: path
, method: method
, headers : headers
, agent: this._agent
});
req.setNoDelay(true)
req.setSocketKeepAlive(true, 0);
function _onError(err) {
cb(undefined, err.message, {});
}
function _onSocket(socket) {
console.log("[SOCKET: " + socket.localPort + "] , " + ((new Date()).getTime() - t) + " , W:" + socket.bytesWritten + " / R:" + socket.bytesRead);
function _onEnd() {
console.log("** END ** ")
}
function _onClose() {
console.log("** CLOSE **");
}
if (!socket.localPort) {
socket.setNoDelay(true)
socket.setKeepAlive(true, 0);
socket.on("end", _onEnd);
socket.on("close", _onClose);
}
}
function _onResponse(response) {
var len = response.headers["content-length"];
var encoding = response.headers["transfer-encoding"];
var payload = "";
console.log(" <<< [RESPONSE: " + response.statusCode+ "] " + (new Date()).getTime() + " , " + ((new Date()).getTime() - t));
function _onEnd() {
switch (response.statusCode) {
case 200: // ok
case 201: // created
try {
payload = JSON.parse(payload || "");
} catch (e) {
self.error("Error parsing payload");
cb(undefined,e.message,{});
return;
/*****************************************************/
}
break;
case 400: // bad request
break;
case 404: // not found
break;
case 409: // conflict
break;
case 415: // Unsupported Media Type
break;
default:
alert("ACK! unknown code: " + response.statusCode);
break;
}
//console.log("PAYLOAD: " + JSON.stringify(payload));
cb(response.statusCode, payload, response.headers);
}
function _onClose() {
console.log(">> CLOSE");
}
function _onData(chunk) {
payload += (chunk || "");
}
self.debug("response returned in (ms): " + ((new Date()).getTime() - t));
// console.log((new Date()).getTime());
response.on("data", _onData);
response.on("end", _onEnd);
response.on("close", _onClose);
}
function _onClose() {
console.log("[CLOSE]");
}
function _onEnd() {
console.log("[END]");
}
req.on("socket", _onSocket);
req.on("response", _onResponse);
req.on("error", _onError);
req.on("close", _onClose);
req.on("end", _onEnd);
console.log(" >>> [REQUEST: " + method + " " + path + "] " + t)
req.end(buf);
}
var __cb = [
function(msg) {
console.log("CONNECTED " + msg);
}
];
var o = new Class();
o._onInit({host: "localhost"
,port: 5984
,name: "stack"});
o.onMsgFor["connect_request_in"].call(o);
thank you
slim
I'm certainly not an expert, but it's probably due to the way they tied the node runtime to the webkit runtime.
Node has a highly optimised, hight streamlined runtime, with only the most necessary running at any one time.
This is not the case in webkit (with regards to server programming at least) as at any moment it will have the rendering engine, any loaded modules/extensions and page scripts the css engine and much more, all churning away.
Check out this link to the Node-Webkit wiki that explains how the runtimes were merged: https://github.com/rogerwang/node-webkit/wiki/How-node.js-is-integrated-with-chromium
Hope this sheds some light!!