// // Usage: // node benchmark/http_simple_auto.js // // Where: // Arguments to pass to `ab`. // Target to benchmark, e.g. `bytes/1024` or `buffer/8192`. // var path = require("path"); var http = require("http"); var spawn = require("child_process").spawn; var port = parseInt(process.env.PORT || 8000); var fixed = "" for (var i = 0; i < 20*1024; i++) { fixed += "C"; } var stored = {}; var storedBuffer = {}; var server = http.createServer(function (req, res) { var commands = req.url.split("/"); var command = commands[1]; var body = ""; var arg = commands[2]; var n_chunks = parseInt(commands[3], 10); var status = 200; if (command == "bytes") { var n = parseInt(arg, 10) if (n <= 0) throw "bytes called with n <= 0" if (stored[n] === undefined) { stored[n] = ""; for (var i = 0; i < n; i++) { stored[n] += "C" } } body = stored[n]; } else if (command == "buffer") { var n = parseInt(arg, 10) if (n <= 0) throw new Error("bytes called with n <= 0"); if (storedBuffer[n] === undefined) { storedBuffer[n] = new Buffer(n); for (var i = 0; i < n; i++) { storedBuffer[n][i] = "C".charCodeAt(0); } } body = storedBuffer[n]; } else if (command == "quit") { res.connection.server.close(); body = "quitting"; } else if (command == "fixed") { body = fixed; } else if (command == "echo") { res.writeHead(200, { "Content-Type": "text/plain", "Transfer-Encoding": "chunked" }); req.pipe(res); return; } else { status = 404; body = "not found\n"; } // example: http://localhost:port/bytes/512/4 // sends a 512 byte body in 4 chunks of 128 bytes if (n_chunks > 0) { res.writeHead(status, { "Content-Type": "text/plain", "Transfer-Encoding": "chunked" }); // send body in chunks var len = body.length; var step = Math.floor(len / n_chunks) || 1; for (var i = 0, n = (n_chunks - 1); i < n; ++i) { res.write(body.slice(i * step, i * step + step)); } res.end(body.slice((n_chunks - 1) * step)); } else { var content_length = body.length.toString(); res.writeHead(status, { "Content-Type": "text/plain", "Content-Length": content_length }); res.end(body); } }); server.listen(port, function () { var url = 'http://127.0.0.1:' + port + '/'; var n = process.argv.length - 1; process.argv[n] = url + process.argv[n]; var cp = spawn('ab', process.argv.slice(2)); cp.stdout.pipe(process.stdout); cp.stderr.pipe(process.stderr); cp.on('exit', function() { server.close(); process.nextTick(dump_mm_stats); }); }); function dump_mm_stats() { if (typeof gc != 'function') return; var before = process.memoryUsage(); for (var i = 0; i < 10; ++i) gc(); var after = process.memoryUsage(); setTimeout(print_stats, 250); // give GC time to settle function print_stats() { console.log('\nBEFORE / AFTER GC'); ['rss', 'heapTotal', 'heapUsed'].forEach(function(key) { var a = before[key] / (1024 * 1024); var b = after[key] / (1024 * 1024); console.log('%sM / %sM %s', a.toFixed(2), b.toFixed(2), key); }); } }