Skip to content

Commit 2b5b931

Browse files
authored
benchmark: cleanup serde_json values being passed around (denoland#9115)
1 parent 271fbe3 commit 2b5b931

File tree

5 files changed

+119
-130
lines changed

5 files changed

+119
-130
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/bench/main.rs

+111-120
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
22

3-
use deno_core::serde_json::{self, map::Map, Number, Value};
3+
use deno_core::serde_json::{self, Value};
4+
use serde::Serialize;
5+
use std::time::SystemTime;
46
use std::{
7+
collections::HashMap,
58
convert::From,
69
env, fs,
710
path::PathBuf,
@@ -102,7 +105,10 @@ const EXEC_TIME_BENCHMARKS: &[(&str, &[&str], Option<i32>)] = &[
102105

103106
const RESULT_KEYS: &[&str] =
104107
&["mean", "stddev", "user", "system", "min", "max"];
105-
fn run_exec_time(deno_exe: &PathBuf, target_dir: &PathBuf) -> Result<Value> {
108+
fn run_exec_time(
109+
deno_exe: &PathBuf,
110+
target_dir: &PathBuf,
111+
) -> Result<HashMap<String, HashMap<String, f64>>> {
106112
let hyperfine_exe = test_util::prebuilt_tool_path("hyperfine");
107113

108114
let benchmark_file = target_dir.join("hyperfine_results.json");
@@ -143,7 +149,7 @@ fn run_exec_time(deno_exe: &PathBuf, target_dir: &PathBuf) -> Result<Value> {
143149
true,
144150
);
145151

146-
let mut results = Map::new();
152+
let mut results = HashMap::<String, HashMap<String, f64>>::new();
147153
let hyperfine_results = read_json(benchmark_file)?;
148154
for ((name, _, _), data) in EXEC_TIME_BENCHMARKS.iter().zip(
149155
hyperfine_results
@@ -157,16 +163,15 @@ fn run_exec_time(deno_exe: &PathBuf, target_dir: &PathBuf) -> Result<Value> {
157163
let data = data.as_object().unwrap().clone();
158164
results.insert(
159165
name.to_string(),
160-
Value::Object(
161-
data
162-
.into_iter()
163-
.filter(|(key, _)| RESULT_KEYS.contains(&key.as_str()))
164-
.collect::<Map<String, Value>>(),
165-
),
166+
data
167+
.into_iter()
168+
.filter(|(key, _)| RESULT_KEYS.contains(&key.as_str()))
169+
.map(|(key, val)| (key, val.as_f64().unwrap()))
170+
.collect(),
166171
);
167172
}
168173

169-
Ok(Value::Object(results))
174+
Ok(results)
170175
}
171176

172177
fn rlib_size(target_dir: &std::path::Path, prefix: &str) -> u64 {
@@ -193,32 +198,29 @@ fn rlib_size(target_dir: &std::path::Path, prefix: &str) -> u64 {
193198

194199
const BINARY_TARGET_FILES: &[&str] =
195200
&["CLI_SNAPSHOT.bin", "COMPILER_SNAPSHOT.bin"];
196-
fn get_binary_sizes(target_dir: &PathBuf) -> Result<Value> {
197-
let mut sizes = Map::new();
198-
let mut mtimes = std::collections::HashMap::new();
201+
fn get_binary_sizes(target_dir: &PathBuf) -> Result<HashMap<String, u64>> {
202+
let mut sizes = HashMap::<String, u64>::new();
203+
let mut mtimes = HashMap::<String, SystemTime>::new();
199204

200205
sizes.insert(
201206
"deno".to_string(),
202-
Value::Number(Number::from(test_util::deno_exe_path().metadata()?.len())),
207+
test_util::deno_exe_path().metadata()?.len(),
203208
);
204209

205210
// add up size for denort
206211
sizes.insert(
207212
"denort".to_string(),
208-
Value::Number(Number::from(test_util::denort_exe_path().metadata()?.len())),
213+
test_util::denort_exe_path().metadata()?.len(),
209214
);
210215

211216
// add up size for everything in target/release/deps/libswc*
212217
let swc_size = rlib_size(&target_dir, "libswc");
213218
println!("swc {} bytes", swc_size);
214-
sizes.insert("swc_rlib".to_string(), Value::Number(swc_size.into()));
219+
sizes.insert("swc_rlib".to_string(), swc_size);
215220

216221
let rusty_v8_size = rlib_size(&target_dir, "librusty_v8");
217222
println!("rusty_v8 {} bytes", rusty_v8_size);
218-
sizes.insert(
219-
"rusty_v8_rlib".to_string(),
220-
Value::Number(rusty_v8_size.into()),
221-
);
223+
sizes.insert("rusty_v8_rlib".to_string(), rusty_v8_size);
222224

223225
// Because cargo's OUT_DIR is not predictable, search the build tree for
224226
// snapshot related files.
@@ -244,18 +246,18 @@ fn get_binary_sizes(target_dir: &PathBuf) -> Result<Value> {
244246
}
245247

246248
mtimes.insert(filename.clone(), file_mtime);
247-
sizes.insert(filename, Value::Number(Number::from(meta.len())));
249+
sizes.insert(filename, meta.len());
248250
}
249251

250-
Ok(Value::Object(sizes))
252+
Ok(sizes)
251253
}
252254

253255
const BUNDLES: &[(&str, &str)] = &[
254256
("file_server", "./std/http/file_server.ts"),
255257
("gist", "./std/examples/gist.ts"),
256258
];
257-
fn bundle_benchmark(deno_exe: &PathBuf) -> Result<Value> {
258-
let mut sizes = Map::new();
259+
fn bundle_benchmark(deno_exe: &PathBuf) -> Result<HashMap<String, u64>> {
260+
let mut sizes = HashMap::<String, u64>::new();
259261

260262
for (name, url) in BUNDLES {
261263
let path = format!("{}.bundle.js", name);
@@ -275,71 +277,48 @@ fn bundle_benchmark(deno_exe: &PathBuf) -> Result<Value> {
275277

276278
let file = PathBuf::from(path);
277279
assert!(file.is_file());
278-
sizes.insert(
279-
name.to_string(),
280-
Value::Number(Number::from(file.metadata()?.len())),
281-
);
280+
sizes.insert(name.to_string(), file.metadata()?.len());
282281
let _ = fs::remove_file(file);
283282
}
284283

285-
Ok(Value::Object(sizes))
284+
Ok(sizes)
286285
}
287286

288-
fn run_throughput(deno_exe: &PathBuf) -> Result<Value> {
289-
let mut m = Map::new();
287+
fn run_throughput(deno_exe: &PathBuf) -> Result<HashMap<String, f64>> {
288+
let mut m = HashMap::<String, f64>::new();
290289

291290
m.insert("100M_tcp".to_string(), throughput::tcp(deno_exe, 100)?);
292291
m.insert("100M_cat".to_string(), throughput::cat(deno_exe, 100)?);
293292
m.insert("10M_tcp".to_string(), throughput::tcp(deno_exe, 10)?);
294293
m.insert("10M_cat".to_string(), throughput::cat(deno_exe, 10)?);
295294

296-
Ok(Value::Object(m))
295+
Ok(m)
297296
}
298297

299-
fn run_http(
300-
target_dir: &PathBuf,
301-
new_data: &mut Map<String, Value>,
302-
) -> Result<()> {
298+
fn run_http(target_dir: &PathBuf, new_data: &mut BenchResult) -> Result<()> {
303299
let stats = http::benchmark(target_dir)?;
304300

305-
new_data.insert(
306-
"req_per_sec".to_string(),
307-
Value::Object(
308-
stats
309-
.iter()
310-
.map(|(name, result)| {
311-
(name.clone(), Value::Number(Number::from(result.requests)))
312-
})
313-
.collect::<Map<String, Value>>(),
314-
),
315-
);
301+
new_data.req_per_sec = stats
302+
.iter()
303+
.map(|(name, result)| (name.clone(), result.requests))
304+
.collect();
316305

317-
new_data.insert(
318-
"max_latency".to_string(),
319-
Value::Object(
320-
stats
321-
.iter()
322-
.map(|(name, result)| {
323-
(
324-
name.clone(),
325-
Value::Number(Number::from_f64(result.latency).unwrap()),
326-
)
327-
})
328-
.collect::<Map<String, Value>>(),
329-
),
330-
);
306+
new_data.max_latency = stats
307+
.iter()
308+
.map(|(name, result)| (name.clone(), result.latency))
309+
.collect();
331310

332311
Ok(())
333312
}
334313

335314
fn run_strace_benchmarks(
336315
deno_exe: &PathBuf,
337-
new_data: &mut Map<String, Value>,
316+
new_data: &mut BenchResult,
338317
) -> Result<()> {
339318
use std::io::Read;
340319

341-
let mut thread_count = Map::new();
342-
let mut syscall_count = Map::new();
320+
let mut thread_count = HashMap::<String, u64>::new();
321+
let mut syscall_count = HashMap::<String, u64>::new();
343322

344323
for (name, args, _) in EXEC_TIME_BENCHMARKS {
345324
let mut file = tempfile::NamedTempFile::new()?;
@@ -361,26 +340,20 @@ fn run_strace_benchmarks(
361340
file.as_file_mut().read_to_string(&mut output)?;
362341

363342
let strace_result = test_util::parse_strace_output(&output);
364-
thread_count.insert(
365-
name.to_string(),
366-
Value::Number(Number::from(
367-
strace_result.get("clone").map(|d| d.calls).unwrap_or(0) + 1,
368-
)),
369-
);
370-
syscall_count.insert(
371-
name.to_string(),
372-
Value::Number(Number::from(strace_result.get("total").unwrap().calls)),
373-
);
343+
let clone = strace_result.get("clone").map(|d| d.calls).unwrap_or(0);
344+
let total = strace_result.get("total").unwrap().calls;
345+
thread_count.insert(name.to_string(), clone);
346+
syscall_count.insert(name.to_string(), total);
374347
}
375348

376-
new_data.insert("thread_count".to_string(), Value::Object(thread_count));
377-
new_data.insert("syscall_count".to_string(), Value::Object(syscall_count));
349+
new_data.thread_count = thread_count;
350+
new_data.syscall_count = syscall_count;
378351

379352
Ok(())
380353
}
381354

382-
fn run_max_mem_benchmark(deno_exe: &PathBuf) -> Result<Value> {
383-
let mut results = Map::new();
355+
fn run_max_mem_benchmark(deno_exe: &PathBuf) -> Result<HashMap<String, u64>> {
356+
let mut results = HashMap::<String, u64>::new();
384357

385358
for (name, args, return_code) in EXEC_TIME_BENCHMARKS {
386359
let proc = Command::new("time")
@@ -396,13 +369,10 @@ fn run_max_mem_benchmark(deno_exe: &PathBuf) -> Result<Value> {
396369
}
397370
let out = String::from_utf8(proc_result.stderr)?;
398371

399-
results.insert(
400-
name.to_string(),
401-
Value::Number(Number::from(test_util::parse_max_mem(&out).unwrap())),
402-
);
372+
results.insert(name.to_string(), test_util::parse_max_mem(&out).unwrap());
403373
}
404374

405-
Ok(Value::Object(results))
375+
Ok(results)
406376
}
407377

408378
fn cargo_deps() -> usize {
@@ -420,6 +390,44 @@ fn cargo_deps() -> usize {
420390
count
421391
}
422392

393+
#[derive(Serialize)]
394+
struct BenchResult {
395+
created_at: String,
396+
sha1: String,
397+
binary_size: HashMap<String, u64>,
398+
bundle_size: HashMap<String, u64>,
399+
cargo_deps: usize,
400+
// TODO(ry) The "benchmark" benchmark should actually be called "exec_time".
401+
// When this is changed, the historical data in gh-pages branch needs to be
402+
// changed too.
403+
benchmark: HashMap<String, HashMap<String, f64>>,
404+
throughput: HashMap<String, f64>,
405+
max_memory: HashMap<String, u64>,
406+
req_per_sec: HashMap<String, u64>,
407+
max_latency: HashMap<String, f64>,
408+
thread_count: HashMap<String, u64>,
409+
syscall_count: HashMap<String, u64>,
410+
}
411+
412+
impl BenchResult {
413+
pub fn new() -> BenchResult {
414+
BenchResult {
415+
created_at: String::new(),
416+
sha1: String::new(),
417+
binary_size: HashMap::new(),
418+
bundle_size: HashMap::new(),
419+
cargo_deps: 0,
420+
benchmark: HashMap::new(),
421+
throughput: HashMap::new(),
422+
max_memory: HashMap::new(),
423+
req_per_sec: HashMap::new(),
424+
max_latency: HashMap::new(),
425+
thread_count: HashMap::new(),
426+
syscall_count: HashMap::new(),
427+
}
428+
}
429+
}
430+
423431
/*
424432
TODO(SyrupThinker)
425433
Switch to the #[bench] attribute once
@@ -439,60 +447,43 @@ fn main() -> Result<()> {
439447

440448
env::set_current_dir(&test_util::root_path())?;
441449

442-
let mut new_data: Map<String, Value> = Map::new();
443-
new_data.insert(
444-
"created_at".to_string(),
445-
Value::String(
446-
chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
447-
),
448-
);
449-
new_data.insert(
450-
"sha1".to_string(),
451-
Value::String(
452-
test_util::run_collect(
453-
&["git", "rev-parse", "HEAD"],
454-
None,
455-
None,
456-
None,
457-
true,
458-
)
459-
.0
460-
.trim()
461-
.to_string(),
462-
),
463-
);
464-
465-
new_data.insert("binary_size".to_string(), get_binary_sizes(&target_dir)?);
466-
new_data.insert("bundle_size".to_string(), bundle_benchmark(&deno_exe)?);
467-
new_data.insert("cargo_deps".to_string(), Value::Number(cargo_deps().into()));
450+
let mut new_data = BenchResult::new();
451+
new_data.created_at =
452+
chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true);
453+
new_data.sha1 = test_util::run_collect(
454+
&["git", "rev-parse", "HEAD"],
455+
None,
456+
None,
457+
None,
458+
true,
459+
)
460+
.0
461+
.trim()
462+
.to_string();
468463

469-
// TODO(ry) The "benchmark" benchmark should actually be called "exec_time".
470-
// When this is changed, the historical data in gh-pages branch needs to be
471-
// changed too.
472-
new_data.insert(
473-
"benchmark".to_string(),
474-
run_exec_time(&deno_exe, &target_dir)?,
475-
);
464+
new_data.binary_size = get_binary_sizes(&target_dir)?;
465+
new_data.bundle_size = bundle_benchmark(&deno_exe)?;
466+
new_data.cargo_deps = cargo_deps();
467+
new_data.benchmark = run_exec_time(&deno_exe, &target_dir)?;
476468

477469
// Cannot run throughput benchmark on windows because they don't have nc or
478470
// pipe.
479471
if cfg!(not(target_os = "windows")) {
480-
new_data.insert("throughput".to_string(), run_throughput(&deno_exe)?);
472+
new_data.throughput = run_throughput(&deno_exe)?;
481473
run_http(&target_dir, &mut new_data)?;
482474
}
483475

484476
if cfg!(target_os = "linux") {
485477
run_strace_benchmarks(&deno_exe, &mut new_data)?;
486-
new_data
487-
.insert("max_memory".to_string(), run_max_mem_benchmark(&deno_exe)?);
478+
new_data.max_memory = run_max_mem_benchmark(&deno_exe)?;
488479
}
489480

490481
println!("===== <BENCHMARK RESULTS>");
491482
serde_json::to_writer_pretty(std::io::stdout(), &new_data)?;
492483
println!("\n===== </BENCHMARK RESULTS>");
493484

494485
if let Some(filename) = target_dir.join("bench.json").to_str() {
495-
write_json(filename, &Value::Object(new_data))?;
486+
write_json(filename, &serde_json::to_value(&new_data)?)?;
496487
} else {
497488
eprintln!("Cannot write bench.json, path is invalid");
498489
}

0 commit comments

Comments
 (0)