Skip to content

Commit

Permalink
[net2] inline write on empty write buffer for performance
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Mar 19, 2010
1 parent 1762abc commit 90295d9
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 3 deletions.
83 changes: 80 additions & 3 deletions lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,83 @@ Stream.prototype.write = function (data, encoding) {

if (!self.writable) throw new Error('Stream is not writable');

if (self._writeQueue && self._writeQueue.length) {
return self._writeQueued(data, encoding); // slow

} else {
// The most common case. There is no write queue. Just push the data
// directly to the socket.

var bytesWritten;
var buffer = data, off = 0, len = data.length;

if (typeof data == 'string') {
encoding = (encoding || 'utf8').toLowerCase();
var bytes = encoding == 'utf8' ? Buffer.utf8ByteLength(data) : data.length;

//debug('write string :' + JSON.stringify(data));

if (!recvBuffer) allocRecvBuffer();

if (recvBuffer.length - recvBuffer.used < bytes) {
// not enough room - go to slow case
return self._writeQueued(data, encoding);
}

var charsWritten;
if (encoding == 'utf8') {
recvBuffer.utf8Write(data, recvBuffer.used);
} else {
// ascii
recvBuffer.asciiWrite(data, recvBuffer.used);
}

buffer = recvBuffer;
off = recvBuffer.used;
len = bytes;
}

//debug('write [fd, off, len] =' + JSON.stringify([self.fd, off, len]));

// Send the buffer.
try {
bytesWritten = write(self.fd, buffer, off, len);
} catch (e) {
self.forceClose(e);
return false;
}

//debug('wrote ' + bytesWritten);

// Note: if using the recvBuffer - we don't need to increase
// recvBuffer.used because it was all sent. Just reuse that space.

if (bytesWritten == len) return true;

//debug('write incomplete ' + bytesWritten + ' < ' + len);

if (buffer == data) {
data.sent = bytesWritten || 0;
data.used = data.length;
} else {
// string
recvBuffer.used += bytesWritten;
data = recvBuffer.slice(off+bytesWritten, off+len+bytesWritten);
data.sent = 0;
data.used = data.length;
}

//if (!self._writeQueue) initWriteStream(self);
self._writeQueue.push(data);
self._writeQueueSize += data.used;
return false;
}
}

Stream.prototype._writeQueued = function (data, encoding) {
//debug('_writeQueued');
var self = this;

if (self.__writeQueueLast() == END_OF_FILE) {
throw new Error('socket.close() called already; cannot write.');
}
Expand Down Expand Up @@ -597,7 +674,7 @@ Stream.prototype.flush = function () {
} else {
b.sent += bytesWritten;
self._writeQueueSize -= bytesWritten;
debug('bytes sent: ' + b.sent);
//debug('bytes sent: ' + b.sent);
}
}
if (self._writeWatcher) self._writeWatcher.stop();
Expand Down Expand Up @@ -654,7 +731,7 @@ Stream.prototype.connect = function () {

if (port >= 0) {
self.fd = socket('tcp');
debug('new fd = ' + self.fd);
//debug('new fd = ' + self.fd);
self.type = 'tcp';
// TODO dns resolution on arguments[1]
var port = arguments[0];
Expand Down Expand Up @@ -726,7 +803,7 @@ Stream.prototype.forceClose = function (exception) {
// FIXME Bug when this.fd == 0
if (this.fd) {
close(this.fd);
debug('close ' + this.fd);
//debug('close ' + this.fd);
this.fd = null;
process.nextTick(function () {
if (exception) self.emit('error', exception);
Expand Down
3 changes: 3 additions & 0 deletions test/simple/test-net-pingpong.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function pingPongTest (port, host) {
socket.setNoDelay();
socket.timeout = 0;

socket.setEncoding('utf8');
socket.addListener("data", function (data) {
puts("server got: " + data);
assert.equal(true, socket.writable);
Expand Down Expand Up @@ -53,6 +54,7 @@ function pingPongTest (port, host) {

var client = net.createConnection(port, host);

client.setEncoding('ascii');
client.addListener("connect", function () {
assert.equal(true, client.readable);
assert.equal(true, client.writable);
Expand Down Expand Up @@ -106,4 +108,5 @@ pingPongTest("/tmp/pingpong.sock");

process.addListener("exit", function () {
assert.equal(4, tests_run);
puts('done');
});

0 comments on commit 90295d9

Please sign in to comment.