Skip to content

Instantly share code, notes, and snippets.

@ceelsoin
Forked from billywhizz/bench.js
Created August 17, 2020 13:47
Show Gist options
  • Save ceelsoin/b5b88aa35299f6a73183c69dd2cf5da0 to your computer and use it in GitHub Desktop.
Save ceelsoin/b5b88aa35299f6a73183c69dd2cf5da0 to your computer and use it in GitHub Desktop.
node.js static file serving benchmark
var TCP = process.binding("tcp_wrap").TCP;
var Buffer = process.binding("buffer").SlowBuffer;
var HTTPParser = process.binding("http_parser").HTTPParser;
function setupSocket(peer) {
function shutdownHandler(status, handle, req) {
// TODO: ensure we only shutdown once
if(status != 0) {
if(peer.onerror) {
var err = new Error("shutdown");
err.errno = errno;
peer.onerror(err);
}
}
handle.close();
if(peer.onclose) peer.onclose();
}
function kill() {
if(!peer.closed) {
peer.readStop();
peer.onread = function() {};
var r = peer.shutdown();
peer.closed = true;
r.oncomplete = shutdownHandler;
}
}
function send(buff, cb) {
var wr = peer.write(buff);
if (!wr) {
if(peer.onerror) {
var err = new Error("write");
err.errno = errno;
peer.onerror(err);
}
peer.kill();
return false;
}
wr.oncomplete = cb;
return true;
}
peer.closed = false;
peer.kill = kill;
peer.send = send;
}
var responses = {
keepalive: "HTTP/1.1 200 OK\r\nServer: node-/0.6.10\r\nDate: Thu, 09 Feb 2012 00:46:42 GMT\r\nContent-Type: text/html\r\nContent-Length: 0\r\nLast-Modified: Tue, 06 Dec 2011 17:29:28 GMT\r\nConnection: keep-alive\r\nAccept-Ranges: bytes\r\n\r\n",
close: "HTTP/1.1 200 OK\r\nServer: nginx/0.7.67\r\nDate: Thu, 09 Feb 2012 00:46:42 GMT\r\nContent-Type: text/html\r\nContent-Length: 0\r\nLast-Modified: Tue, 06 Dec 2011 17:29:28 GMT\r\nConnection: close\r\nAccept-Ranges: bytes\r\n\r\n"
}
for (name in responses) {
var b = new Buffer(responses[name].length);
b.asciiWrite(responses[name]);
responses[name] = b;
}
var FreeList = function(name, max, constructor) {
this.name = name;
this.constructor = constructor;
this.max = max;
this.list = [];
};
FreeList.prototype.alloc = function() {
return this.list.length ? this.list.shift() : this.constructor.apply(this, arguments);
};
FreeList.prototype.free = function(obj) {
if (this.list.length < this.max) this.list.push(obj);
};
var HTTPParsers = new FreeList("HTTPParsers", 1024, function() {
var parser = new HTTPParser(HTTPParser.REQUEST);
parser.onHeadersComplete = function(info) {
var peer = this.peer;
peer.info = info
};
parser.onMessageComplete = function() {
var peer = this.peer;
peer.send(peer.info.shouldKeepAlive?responses.keepalive:responses.close, function(status, handle, req) {
if(status != 0) {
var err = new Error("write");
err.errno = errno;
console.error(err);
peer.kill();
return;
}
if(!peer.info.shouldKeepAlive) peer.kill();
});
};
return parser;
});
function onConnection(peer) {
if(!peer) {
var err = new Error("accept");
err.errno = errno;
console.error(err);
return;
}
setupSocket(peer);
var parser = HTTPParsers.alloc();
parser.peer = peer;
peer.onread = function(buf, start, len) {
if(!buf) {
var err = new Error("EOF");
err.errno = errno;
console.error(err);
peer.kill();
return;
}
var r = parser.execute(buf, start, len);
if(r < 0) {
var err = new Error("parse");
console.error(err);
peer.kill();
return;
}
}
peer.onerror = function(err) {
console.error(err);
}
peer.onclose = function() {
HTTPParsers.free(parser);
}
peer.readStart();
}
var sock = new TCP();
sock.bind("0.0.0.0", 80);
sock.onconnection = onConnection;
sock.listen();
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 16384;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log off;
sendfile off;
tcp_nopush on;
tcp_nodelay on;
open_file_cache max=1000 inactive=3600s;
keepalive_timeout 65;
keepalive_requests 100000;
server {
listen 82;
server_name _;
location / {
root /tmp;
index index.html;
}
error_page 404 /404.html;
location = /404.html {
root /var/www/html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/html;
}
}
}
ab -k -c 20 -n 50000 http://127.0.0.1/0k.txt
Server Software: node-/0.6.10
Server Hostname: 127.0.0.1
Server Port: 80
Document Path: /0k.txt
Document Length: 0 bytes
Concurrency Level: 20
Time taken for tests: 1.821 seconds
Complete requests: 50000
Failed requests: 0
Write errors: 0
Keep-Alive requests: 50000
Total transferred: 10700000 bytes
HTML transferred: 0 bytes
Requests per second: 27450.96 [#/sec] (mean)
Time per request: 0.729 [ms] (mean)
Time per request: 0.036 [ms] (mean, across all concurrent requests)
Transfer rate: 5736.82 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 1
Processing: 0 1 0.1 1 4
Waiting: 0 1 0.1 1 4
Total: 1 1 0.1 1 4
Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 1
80% 1
90% 1
95% 1
98% 1
99% 1
100% 4 (longest request)
ab -k -c 20 -n 50000 http://127.0.0.1:82/0k.txt
Server Software: nginx/0.7.67
Server Hostname: 127.0.0.1
Server Port: 82
Document Path: /0k.txt
Document Length: 0 bytes
Concurrency Level: 20
Time taken for tests: 1.052 seconds
Complete requests: 50000
Failed requests: 0
Write errors: 0
Keep-Alive requests: 50000
Total transferred: 10750000 bytes
HTML transferred: 0 bytes
Requests per second: 47543.16 [#/sec] (mean)
Time per request: 0.421 [ms] (mean)
Time per request: 0.021 [ms] (mean, across all concurrent requests)
Transfer rate: 9982.21 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 1
Processing: 0 0 0.2 0 1
Waiting: 0 0 0.2 0 1
Total: 0 0 0.2 0 1
Percentage of the requests served within a certain time (ms)
50% 0
66% 1
75% 1
80% 1
90% 1
95% 1
98% 1
99% 1
100% 1 (longest request)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment