我注意到了node.js中以下代码性能的奇怪行为。当content
的大小为1.4KB时,请求的响应时间大约为16ms。但是,当content
的大小仅为988字节时,请求的响应时间会更长,大致 200ms :
response.writeHead(200, {"Content-Type": "application/json"});
response.write(JSON.stringify(content, null, 0));
response.end();
这似乎不直观。查看Firebug的网络标签,增加/差异全部来自接收(另一方面等待是两个16ms)。
我做了以下更改来修复它,以便两种情况都有16ms的响应时间:
response.writeHead(200, {"Content-Type": "application/json"});
response.end(JSON.stringify(content, null, 0));
我查看了node.js doc,但到目前为止还没有找到相关信息。我的猜测这与缓冲有关,但node.js可以在write()
和end()
之间抢占吗?
更新
这是在Linux上的v0.10.1上测试的。
我试图查看source,并确定了2路径之间的区别。第一个版本有2个Socket.write调用。
writeHead(...)
write(chunk)
chunk = Buffer.byteLength(chunk).toString(16) + CRLF + chunk + CRLF;
ret = this._send(chunk);
this._writeRaw(chunk);
this.connection.write(chunk);
end()
ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk.
this._writeRaw(chunk);
this.connection.write(chunk);
第二个好的版本只有1个Socket.write调用:
writeHead(...)
end(chunk)
var l = Buffer.byteLength(chunk).toString(16);
ret = this.connection.write(this._header + l + CRLF +
chunk + '\r\n0\r\n' +
this._trailer + '\r\n', encoding);
仍然不确定是什么原因导致第一个版本在响应量较小时效果不佳。
答案 0 :(得分:9)
简答:
您可以明确设置 Content-Length
标头。它会将响应时间从200毫秒减少到20毫秒。
var body = JSON.stringify(content, null, 0);
response.writeHead(200, {
"Content-Type": "application/json",
'Content-Length': body.length
});
response.write(content);
response.end();
事实:
经过几次实验后,我发现,如果 content
足够小(在我的情况下,小于1310字节),单个MTU到继续,响应时间约为200ms 。但是,对于大于该值的任何content
,响应时间大约为20毫秒。
然后我使用wireshark来捕获服务器端的网络包。以下是典型结果:
对于小content
:
response.write(content)
response.end()
对于较大的content
:
response.write(content)
//发送第一个MTU response.end()
可能的解释:
如果未设置Content-Length
标头,则数据将以“Chunked”模式传输。在“Chunked”模式下,服务器和客户端都不知道数据的确切长度,因此客户端会等待(200ms)以查看是否有任何后续软件包。
然而,这个解释提出了另一个问题:为什么在较大的 content
情况下,客户端没有等待200毫秒(相反,它只等了大约50毫秒)?< /强>