Skip to content

Commit

Permalink
First pass at http benchmark.
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Oct 16, 2018
1 parent 1aeda1f commit e411870
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 1 deletion.
34 changes: 34 additions & 0 deletions tests/http_bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Used for benchmarking Deno's networking. See tools/http_benchmark.py
// TODO Replace this with a real HTTP server once
// https://github.com/denoland/deno/issues/726 is completed.
import * as deno from "deno";
const addr = deno.args[1] || "127.0.0.1:4500";
const listener = deno.listen("tcp", addr);
const response = new TextEncoder().encode(
"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n"
);

async function handle(conn: deno.Conn): Promise<void> {
const buffer = new Uint8Array(1024);
try {
while (true) {
const r = await conn.read(buffer);
if (r.eof) {
break;
}
await conn.write(response);
}
} finally {
conn.close();
}
}

async function main(): Promise<void> {
console.log("Listening on", addr);
while (true) {
const conn = await listener.accept();
handle(conn);
}
}

main();
2 changes: 1 addition & 1 deletion third_party
2 changes: 2 additions & 0 deletions tools/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import tempfile
import http_server
import throughput_benchmark
from http_benchmark import http_benchmark

# The list of the tuples of the benchmark name and arguments
exec_time_benchmarks = [
Expand Down Expand Up @@ -183,6 +184,7 @@ def main(argv):
# pipe.
if os.name != 'nt':
new_data["throughput"] = run_throughput(deno_path)
new_data["req_per_sec"] = http_benchmark(deno_path)
if "linux" in sys.platform:
# Thread count test, only on linux
new_data["thread_count"] = run_thread_count_benchmark(deno_path)
Expand Down
49 changes: 49 additions & 0 deletions tools/http_benchmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python

import os
import sys
import util
import time
import subprocess

ADDR = "127.0.0.1:4544"
DURATION = "10s"


def http_benchmark(deno_exe):
deno_cmd = [deno_exe, "--allow-net", "tests/http_bench.ts", ADDR]
node_cmd = ["node", "tools/node_http.js", ADDR.split(":")[1]]

print "http_benchmark testing DENO."
deno_rps = run(deno_cmd)

print "http_benchmark testing NODE."
node_rps = run(node_cmd)

return {"deno": deno_rps, "node": node_rps}


def run(server_cmd):
# Run deno echo server in the background.
server = subprocess.Popen(server_cmd)
time.sleep(5) # wait for server to wake up. TODO racy.
wrk_platform = {
"linux2": "linux",
"darwin": "mac",
}[sys.platform]
try:
cmd = "third_party/wrk/" + wrk_platform + "/wrk -d " + DURATION + " http://" + ADDR + "/"
print cmd
output = subprocess.check_output(cmd, shell=True)
req_per_sec = util.parse_wrk_output(output)
print output
return req_per_sec
finally:
server.kill()


if __name__ == '__main__':
if len(sys.argv) < 2:
print "Usage ./tools/tcp_http_benchmark.py out/debug/deno"
sys.exit(1)
http_benchmark(sys.argv[1])
8 changes: 8 additions & 0 deletions tools/node_http.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const http = require("http");
const port = process.argv[2] || "4544";
console.log("port", port);
http
.Server((req, res) => {
res.end("Hello World\n");
})
.listen(port);
9 changes: 9 additions & 0 deletions tools/testdata/wrk1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Running 10s test @ http://127.0.0.1:4500/
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.08ms 1.37ms 34.96ms 96.63%
Req/Sec 0.92k 51.83 1.00k 78.50%
18381 requests in 10.00s, 0.89MB read
Socket errors: connect 0, read 18381, write 0, timeout 0
Requests/sec: 1837.86
Transfer/sec: 91.53KB
8 changes: 8 additions & 0 deletions tools/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,11 @@ def extract_number(pattern, string):
if len(matches) != 1:
return None
return int(matches[0])


def parse_wrk_output(output):
req_per_sec = None
for line in output.split("\n"):
if req_per_sec is None:
req_per_sec = extract_number(r'Requests/sec:\s+(\d+)', line)
return req_per_sec
8 changes: 8 additions & 0 deletions tools/util_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,19 @@ def parse_unit_test_output_test():
assert expected == None


def parse_wrk_output_test():
print "Testing util.parse_wrk_output_test()..."
f = open(os.path.join(util.root_path, "tools/testdata/wrk1.txt"))
req_per_sec = util.parse_wrk_output(f.read())
assert req_per_sec == 1837


def util_test():
pattern_match_test()
parse_exit_code_test()
shell_quote_win_test()
parse_unit_test_output_test()
parse_wrk_output_test()


if __name__ == '__main__':
Expand Down
23 changes: 23 additions & 0 deletions website/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export function createThroughputColumns(data) {
return createColumns(data, "throughput");
}

export function createReqPerSecColumns(data) {
return createColumns(data, "req_per_sec");
}

export function createBinarySizeColumns(data) {
const propName = "binary_size";
const binarySizeNames = Object.keys(data[data.length - 1][propName]);
Expand Down Expand Up @@ -132,6 +136,7 @@ export async function main() {

const execTimeColumns = createExecTimeColumns(data);
const throughputColumns = createThroughputColumns(data);
const reqPerSecColumns = createReqPerSecColumns(data);
const binarySizeColumns = createBinarySizeColumns(data);
const threadCountColumns = createThreadCountColumns(data);
const syscallCountColumns = createSyscallCountColumns(data);
Expand Down Expand Up @@ -188,6 +193,24 @@ export async function main() {
}
});

c3.generate({
bindto: "#req-per-sec-chart",
data: {
columns: reqPerSecColumns,
onclick: viewCommitOnClick(sha1List)
},
axis: {
x: {
type: "category",
show: false,
categories: sha1ShortList
},
y: {
label: "seconds"
}
}
});

c3.generate({
bindto: "#binary-size-chart",
data: {
Expand Down
8 changes: 8 additions & 0 deletions website/app_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ const regularData = [
"10M_tcp": 1.6,
"10M_cat": 1.0
},
req_per_sec: {
node: 16000,
deno: 1000
},
benchmark: {
hello: {
mean: 0.05
Expand Down Expand Up @@ -66,6 +70,10 @@ const regularData = [
"10M_tcp": 1.6,
"10M_cat": 1.0
},
req_per_sec: {
node: 1600,
deno: 3.0
},
benchmark: {
hello: {
mean: 0.055
Expand Down
4 changes: 4 additions & 0 deletions website/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ <h2>Execution time</h2>
<h2>Throughput</h2>
<div id="throughput-chart"></div>

<h2>Req/Sec</h2>
Tests HTTP server performance against Node.
<div id="req-per-sec-chart"></div>

<h2>Executable size</h2>
deno ships only a single binary. We track its size here.
<div id="binary-size-chart"></div>
Expand Down

0 comments on commit e411870

Please sign in to comment.