mirror of
https://github.com/denoland/deno.git
synced 2024-11-27 16:10:57 -05:00
bench: remove http benchmarks (#26484)
These benchmarks run on GitHub Actions and are extremely noisy, thus not providing much value.
This commit is contained in:
parent
09e36d41b0
commit
fd8bf08271
10 changed files with 2 additions and 291 deletions
|
@ -1,167 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::net::TcpStream;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::sync::atomic::AtomicU16;
|
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
use std::time::Duration;
|
|
||||||
use std::time::Instant;
|
|
||||||
|
|
||||||
use super::Result;
|
|
||||||
|
|
||||||
pub use test_util::parse_wrk_output;
|
|
||||||
pub use test_util::WrkOutput as HttpBenchmarkResult;
|
|
||||||
// Some of the benchmarks in this file have been renamed. In case the history
|
|
||||||
// somehow gets messed up:
|
|
||||||
// "node_http" was once called "node"
|
|
||||||
// "deno_tcp" was once called "deno"
|
|
||||||
// "deno_http" was once called "deno_net_http"
|
|
||||||
|
|
||||||
const DURATION: &str = "10s";
|
|
||||||
|
|
||||||
pub fn benchmark(
|
|
||||||
target_path: &Path,
|
|
||||||
) -> Result<HashMap<String, HttpBenchmarkResult>> {
|
|
||||||
let deno_exe = test_util::deno_exe_path();
|
|
||||||
let deno_exe = deno_exe.to_string();
|
|
||||||
|
|
||||||
let hyper_hello_exe = target_path.join("test_server");
|
|
||||||
let hyper_hello_exe = hyper_hello_exe.to_str().unwrap();
|
|
||||||
|
|
||||||
let mut res = HashMap::new();
|
|
||||||
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
|
|
||||||
let http_dir = manifest_dir.join("bench").join("http");
|
|
||||||
for entry in std::fs::read_dir(&http_dir)? {
|
|
||||||
let entry = entry?;
|
|
||||||
let pathbuf = entry.path();
|
|
||||||
let path = pathbuf.to_str().unwrap();
|
|
||||||
if path.ends_with(".lua") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let file_stem = pathbuf.file_stem().unwrap().to_str().unwrap();
|
|
||||||
|
|
||||||
let lua_script = http_dir.join(format!("{file_stem}.lua"));
|
|
||||||
let mut maybe_lua = None;
|
|
||||||
if lua_script.exists() {
|
|
||||||
maybe_lua = Some(lua_script.to_str().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
let port = get_port();
|
|
||||||
// deno run -A --unstable-net <path> <addr>
|
|
||||||
res.insert(
|
|
||||||
file_stem.to_string(),
|
|
||||||
run(
|
|
||||||
&[
|
|
||||||
deno_exe.as_str(),
|
|
||||||
"run",
|
|
||||||
"--allow-all",
|
|
||||||
"--unstable-net",
|
|
||||||
"--enable-testing-features-do-not-use",
|
|
||||||
path,
|
|
||||||
&server_addr(port),
|
|
||||||
],
|
|
||||||
port,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
maybe_lua,
|
|
||||||
)?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.insert("hyper".to_string(), hyper_http(hyper_hello_exe)?);
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(
|
|
||||||
server_cmd: &[&str],
|
|
||||||
port: u16,
|
|
||||||
env: Option<Vec<(String, String)>>,
|
|
||||||
origin_cmd: Option<&[&str]>,
|
|
||||||
lua_script: Option<&str>,
|
|
||||||
) -> Result<HttpBenchmarkResult> {
|
|
||||||
// Wait for port 4544 to become available.
|
|
||||||
// TODO Need to use SO_REUSEPORT with tokio::net::TcpListener.
|
|
||||||
std::thread::sleep(Duration::from_secs(5));
|
|
||||||
|
|
||||||
let mut origin = None;
|
|
||||||
if let Some(cmd) = origin_cmd {
|
|
||||||
let mut com = Command::new(cmd[0]);
|
|
||||||
com.args(&cmd[1..]);
|
|
||||||
if let Some(env) = env.clone() {
|
|
||||||
com.envs(env);
|
|
||||||
}
|
|
||||||
origin = Some(com.spawn()?);
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("{}", server_cmd.join(" "));
|
|
||||||
let mut server = {
|
|
||||||
let mut com = Command::new(server_cmd[0]);
|
|
||||||
com.args(&server_cmd[1..]);
|
|
||||||
if let Some(env) = env {
|
|
||||||
com.envs(env);
|
|
||||||
}
|
|
||||||
com.spawn()?
|
|
||||||
};
|
|
||||||
|
|
||||||
// Wait for server to wake up.
|
|
||||||
let now = Instant::now();
|
|
||||||
let addr = format!("127.0.0.1:{port}");
|
|
||||||
while now.elapsed().as_secs() < 30 {
|
|
||||||
if TcpStream::connect(&addr).is_ok() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
std::thread::sleep(Duration::from_millis(10));
|
|
||||||
}
|
|
||||||
TcpStream::connect(&addr).expect("Failed to connect to server in time");
|
|
||||||
println!("Server took {} ms to start", now.elapsed().as_millis());
|
|
||||||
|
|
||||||
let wrk = test_util::prebuilt_tool_path("wrk");
|
|
||||||
assert!(wrk.is_file());
|
|
||||||
|
|
||||||
let addr = format!("http://{addr}/");
|
|
||||||
let wrk = wrk.to_string();
|
|
||||||
let mut wrk_cmd = vec![wrk.as_str(), "-d", DURATION, "--latency", &addr];
|
|
||||||
|
|
||||||
if let Some(lua_script) = lua_script {
|
|
||||||
wrk_cmd.push("-s");
|
|
||||||
wrk_cmd.push(lua_script);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("{}", wrk_cmd.join(" "));
|
|
||||||
let output = test_util::run_collect(&wrk_cmd, None, None, None, true).0;
|
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_secs(1)); // wait to capture failure. TODO racy.
|
|
||||||
|
|
||||||
println!("{output}");
|
|
||||||
assert!(
|
|
||||||
server.try_wait()?.map(|s| s.success()).unwrap_or(true),
|
|
||||||
"server ended with error"
|
|
||||||
);
|
|
||||||
|
|
||||||
server.kill()?;
|
|
||||||
if let Some(mut origin) = origin {
|
|
||||||
origin.kill()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(parse_wrk_output(&output))
|
|
||||||
}
|
|
||||||
|
|
||||||
static NEXT_PORT: AtomicU16 = AtomicU16::new(4544);
|
|
||||||
pub(crate) fn get_port() -> u16 {
|
|
||||||
let p = NEXT_PORT.load(Ordering::SeqCst);
|
|
||||||
NEXT_PORT.store(p.wrapping_add(1), Ordering::SeqCst);
|
|
||||||
p
|
|
||||||
}
|
|
||||||
|
|
||||||
fn server_addr(port: u16) -> String {
|
|
||||||
format!("0.0.0.0:{port}")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hyper_http(exe: &str) -> Result<HttpBenchmarkResult> {
|
|
||||||
let port = get_port();
|
|
||||||
println!("http_benchmark testing RUST hyper");
|
|
||||||
run(&[exe, &port.to_string()], port, None, None, None)
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
import { Hono } from "https://deno.land/x/hono@v2.0.9/mod.ts";
|
|
||||||
|
|
||||||
const addr = Deno.args[0] || "127.0.0.1:4500";
|
|
||||||
const [hostname, port] = addr.split(":");
|
|
||||||
|
|
||||||
const app = new Hono();
|
|
||||||
app.get("/", (c) => c.text("Hello, World!"));
|
|
||||||
|
|
||||||
Deno.serve({ port: Number(port), hostname }, app.fetch);
|
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
const addr = Deno.args[0] || "127.0.0.1:4500";
|
|
||||||
const [hostname, port] = addr.split(":");
|
|
||||||
const { serve } = Deno;
|
|
||||||
|
|
||||||
const path = new URL("../testdata/128k.bin", import.meta.url).pathname;
|
|
||||||
|
|
||||||
function handler() {
|
|
||||||
const file = Deno.openSync(path);
|
|
||||||
return new Response(file.readable);
|
|
||||||
}
|
|
||||||
|
|
||||||
serve({ hostname, port: Number(port) }, handler);
|
|
|
@ -1,5 +0,0 @@
|
||||||
wrk.headers["foo"] = "bar"
|
|
||||||
wrk.headers["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
|
|
||||||
wrk.headers["Viewport-Width"] = "1920"
|
|
||||||
wrk.headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
|
|
||||||
wrk.headers["Accept-Language"] = "en,la;q=0.9"
|
|
|
@ -1,11 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
const addr = Deno.args[0] ?? "127.0.0.1:4500";
|
|
||||||
const [hostname, port] = addr.split(":");
|
|
||||||
const { serve } = Deno;
|
|
||||||
|
|
||||||
function handler() {
|
|
||||||
return new Response("Hello World");
|
|
||||||
}
|
|
||||||
|
|
||||||
serve({ hostname, port: Number(port), reusePort: true }, handler);
|
|
|
@ -1,5 +0,0 @@
|
||||||
wrk.method = "POST"
|
|
||||||
wrk.headers["Content-Type"] = "application/octet-stream"
|
|
||||||
|
|
||||||
file = io.open("./cli/bench/testdata/128k.bin", "rb")
|
|
||||||
wrk.body = file:read("*a")
|
|
|
@ -1,3 +0,0 @@
|
||||||
wrk.method = "POST"
|
|
||||||
wrk.headers["Content-Type"] = "application/json"
|
|
||||||
wrk.body = '{"hello":"deno"}'
|
|
|
@ -1,25 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
import { renderToReadableStream } from "https://esm.run/react-dom/server";
|
|
||||||
import * as React from "https://esm.run/react";
|
|
||||||
const { serve } = Deno;
|
|
||||||
const addr = Deno.args[0] || "127.0.0.1:4500";
|
|
||||||
const [hostname, port] = addr.split(":");
|
|
||||||
|
|
||||||
const App = () => (
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<h1>Hello World</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "text/html",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
serve({ hostname, port: Number(port) }, async () => {
|
|
||||||
return new Response(await renderToReadableStream(<App />), headers);
|
|
||||||
});
|
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
// Used for benchmarking Deno's networking.
|
|
||||||
// TODO(bartlomieju): Replace this with a real HTTP server once
|
|
||||||
// https://github.com/denoland/deno/issues/726 is completed.
|
|
||||||
// Note: this is a keep-alive server.
|
|
||||||
// deno-lint-ignore-file no-console
|
|
||||||
const addr = Deno.args[0] || "127.0.0.1:4500";
|
|
||||||
const [hostname, port] = addr.split(":");
|
|
||||||
const listener = Deno.listen({ hostname, port: Number(port) });
|
|
||||||
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) {
|
|
||||||
await conn.read(buffer);
|
|
||||||
await conn.write(response);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (
|
|
||||||
!(e instanceof Deno.errors.BrokenPipe) &&
|
|
||||||
!(e instanceof Deno.errors.ConnectionReset)
|
|
||||||
) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conn.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Listening on", addr);
|
|
||||||
for await (const conn of listener) {
|
|
||||||
handle(conn);
|
|
||||||
}
|
|
|
@ -17,7 +17,6 @@ use std::process::Stdio;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use test_util::PathRef;
|
use test_util::PathRef;
|
||||||
|
|
||||||
mod http;
|
|
||||||
mod lsp;
|
mod lsp;
|
||||||
|
|
||||||
fn read_json(filename: &Path) -> Result<Value> {
|
fn read_json(filename: &Path) -> Result<Value> {
|
||||||
|
@ -345,9 +344,11 @@ struct BenchResult {
|
||||||
binary_size: HashMap<String, i64>,
|
binary_size: HashMap<String, i64>,
|
||||||
bundle_size: HashMap<String, i64>,
|
bundle_size: HashMap<String, i64>,
|
||||||
cargo_deps: usize,
|
cargo_deps: usize,
|
||||||
|
// TODO(bartlomieju): remove
|
||||||
max_latency: HashMap<String, f64>,
|
max_latency: HashMap<String, f64>,
|
||||||
max_memory: HashMap<String, i64>,
|
max_memory: HashMap<String, i64>,
|
||||||
lsp_exec_time: HashMap<String, i64>,
|
lsp_exec_time: HashMap<String, i64>,
|
||||||
|
// TODO(bartlomieju): remove
|
||||||
req_per_sec: HashMap<String, i64>,
|
req_per_sec: HashMap<String, i64>,
|
||||||
syscall_count: HashMap<String, i64>,
|
syscall_count: HashMap<String, i64>,
|
||||||
thread_count: HashMap<String, i64>,
|
thread_count: HashMap<String, i64>,
|
||||||
|
@ -362,7 +363,6 @@ async fn main() -> Result<()> {
|
||||||
"binary_size",
|
"binary_size",
|
||||||
"cargo_deps",
|
"cargo_deps",
|
||||||
"lsp",
|
"lsp",
|
||||||
"http",
|
|
||||||
"strace",
|
"strace",
|
||||||
"mem_usage",
|
"mem_usage",
|
||||||
];
|
];
|
||||||
|
@ -427,21 +427,6 @@ async fn main() -> Result<()> {
|
||||||
new_data.lsp_exec_time = lsp_exec_times;
|
new_data.lsp_exec_time = lsp_exec_times;
|
||||||
}
|
}
|
||||||
|
|
||||||
if benchmarks.contains(&"http") && cfg!(not(target_os = "windows")) {
|
|
||||||
let stats = http::benchmark(target_dir.as_path())?;
|
|
||||||
let req_per_sec = stats
|
|
||||||
.iter()
|
|
||||||
.map(|(name, result)| (name.clone(), result.requests as i64))
|
|
||||||
.collect();
|
|
||||||
new_data.req_per_sec = req_per_sec;
|
|
||||||
let max_latency = stats
|
|
||||||
.iter()
|
|
||||||
.map(|(name, result)| (name.clone(), result.latency))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
new_data.max_latency = max_latency;
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg!(target_os = "linux") && benchmarks.contains(&"strace") {
|
if cfg!(target_os = "linux") && benchmarks.contains(&"strace") {
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue