Fix buffering logic for HTTP outgoing messages.
authorRyan Dahl <ry@tinyclouds.org>
Mon, 14 Sep 2009 14:25:41 +0000 (16:25 +0200)
committerRyan Dahl <ry@tinyclouds.org>
Mon, 14 Sep 2009 14:25:41 +0000 (16:25 +0200)
Was sending two packets instead of one for some short messages, and even 3,
for short chunked-encoded messages. Also use the more general Encode()
function for receiving HTTP bodies.

Gives ~6% improvement on "hello world" web server benchmarks.

src/http.cc
src/http.js

index 8d697bd..d0202a0 100644 (file)
@@ -191,23 +191,8 @@ HTTPConnection::on_body (http_parser *parser, const char *buf, size_t len)
 
   // TODO each message should have their encoding.
   // don't look at the conneciton for encoding
-
-  if (connection->encoding_ == RAW) {
-    // raw encoding
-    Local<Array> array = Array::New(len);
-    for (size_t i = 0; i < len; i++) {
-      unsigned char val = reinterpret_cast<const unsigned char*>(buf)[i];
-      array->Set(Integer::New(i), Integer::New(val));
-    }
-    argv[0] = array;
-
-  } else {
-    // utf8 or ascii encoding
-    Handle<String> chunk = String::New((const char*)buf, len);
-    argv[0] = chunk;
-  }
-
-  connection->Emit("body", 1, argv);
+  Local<Value> data = Encode(buf, len, connection->encoding_);
+  connection->Emit("body", 1, &data);
 
   return 0;
 }
index 3048c15..777bfd5 100644 (file)
@@ -167,13 +167,37 @@ function OutgoingMessage () {
   this.should_keep_alive = true;
   this.use_chunked_encoding_by_default = true;
 
+  this.flushing = false;
+
   this.finished = false;
 }
 node.inherits(OutgoingMessage, node.EventEmitter);
 
 OutgoingMessage.prototype.send = function (data, encoding) {
+  var length = this.output.length;
+
+  if (length === 0) {
+    this.output.push(data);
+    encoding = encoding || (data.constructor === Array ? "raw" : "ascii");
+    this.outputEncodings.push(encoding);
+    return;
+  }
+
+  var lastEncoding = this.outputEncodings[length-1];
+  var lastData = this.output[length-1];
+
+  if ((lastEncoding === encoding) ||
+      (!encoding && data.constructor === lastData.constructor)) {
+    if (lastData.constructor === String) {
+      this.output[length-1] = lastData + data;
+    } else {
+      this.output[length-1] = lastData.concat(data);
+    }
+    return;
+  }
+
   this.output.push(data);
-  encoding = encoding || (data.constructor === Array ? "raw" : "raws");
+  encoding = encoding || (data.constructor === Array ? "raw" : "ascii");
   this.outputEncodings.push(encoding);
 };
 
@@ -237,15 +261,19 @@ OutgoingMessage.prototype.sendHeaderLines = function (first_line, headers) {
 
 OutgoingMessage.prototype.sendBody = function (chunk, encoding) {
   if (this.chunked_encoding) {
-    this.send(chunk.length.toString(16), "ascii");
-    this.send(CRLF, "ascii");
+    this.send(chunk.length.toString(16));
+    this.send(CRLF);
     this.send(chunk, encoding);
-    this.send(CRLF, "ascii");
+    this.send(CRLF);
   } else {
     this.send(chunk, encoding);
   }
 
-  this.flush();
+  if (this.flushing) {
+    this.flush();
+  } else {
+    this.flushing = true;
+  }
 };
 
 OutgoingMessage.prototype.flush = function () {