1
1
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
2
2
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 ;
4
6
use std:: {
7
+ collections:: HashMap ,
5
8
convert:: From ,
6
9
env, fs,
7
10
path:: PathBuf ,
@@ -102,7 +105,10 @@ const EXEC_TIME_BENCHMARKS: &[(&str, &[&str], Option<i32>)] = &[
102
105
103
106
const RESULT_KEYS : & [ & str ] =
104
107
& [ "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 > > > {
106
112
let hyperfine_exe = test_util:: prebuilt_tool_path ( "hyperfine" ) ;
107
113
108
114
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> {
143
149
true ,
144
150
) ;
145
151
146
- let mut results = Map :: new ( ) ;
152
+ let mut results = HashMap :: < String , HashMap < String , f64 > > :: new ( ) ;
147
153
let hyperfine_results = read_json ( benchmark_file) ?;
148
154
for ( ( name, _, _) , data) in EXEC_TIME_BENCHMARKS . iter ( ) . zip (
149
155
hyperfine_results
@@ -157,16 +163,15 @@ fn run_exec_time(deno_exe: &PathBuf, target_dir: &PathBuf) -> Result<Value> {
157
163
let data = data. as_object ( ) . unwrap ( ) . clone ( ) ;
158
164
results. insert (
159
165
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 ( ) ,
166
171
) ;
167
172
}
168
173
169
- Ok ( Value :: Object ( results) )
174
+ Ok ( results)
170
175
}
171
176
172
177
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 {
193
198
194
199
const BINARY_TARGET_FILES : & [ & str ] =
195
200
& [ "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 ( ) ;
199
204
200
205
sizes. insert (
201
206
"deno" . to_string ( ) ,
202
- Value :: Number ( Number :: from ( test_util:: deno_exe_path ( ) . metadata ( ) ?. len ( ) ) ) ,
207
+ test_util:: deno_exe_path ( ) . metadata ( ) ?. len ( ) ,
203
208
) ;
204
209
205
210
// add up size for denort
206
211
sizes. insert (
207
212
"denort" . to_string ( ) ,
208
- Value :: Number ( Number :: from ( test_util:: denort_exe_path ( ) . metadata ( ) ?. len ( ) ) ) ,
213
+ test_util:: denort_exe_path ( ) . metadata ( ) ?. len ( ) ,
209
214
) ;
210
215
211
216
// add up size for everything in target/release/deps/libswc*
212
217
let swc_size = rlib_size ( & target_dir, "libswc" ) ;
213
218
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) ;
215
220
216
221
let rusty_v8_size = rlib_size ( & target_dir, "librusty_v8" ) ;
217
222
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) ;
222
224
223
225
// Because cargo's OUT_DIR is not predictable, search the build tree for
224
226
// snapshot related files.
@@ -244,18 +246,18 @@ fn get_binary_sizes(target_dir: &PathBuf) -> Result<Value> {
244
246
}
245
247
246
248
mtimes. insert ( filename. clone ( ) , file_mtime) ;
247
- sizes. insert ( filename, Value :: Number ( Number :: from ( meta. len ( ) ) ) ) ;
249
+ sizes. insert ( filename, meta. len ( ) ) ;
248
250
}
249
251
250
- Ok ( Value :: Object ( sizes) )
252
+ Ok ( sizes)
251
253
}
252
254
253
255
const BUNDLES : & [ ( & str , & str ) ] = & [
254
256
( "file_server" , "./std/http/file_server.ts" ) ,
255
257
( "gist" , "./std/examples/gist.ts" ) ,
256
258
] ;
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 ( ) ;
259
261
260
262
for ( name, url) in BUNDLES {
261
263
let path = format ! ( "{}.bundle.js" , name) ;
@@ -275,71 +277,48 @@ fn bundle_benchmark(deno_exe: &PathBuf) -> Result<Value> {
275
277
276
278
let file = PathBuf :: from ( path) ;
277
279
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 ( ) ) ;
282
281
let _ = fs:: remove_file ( file) ;
283
282
}
284
283
285
- Ok ( Value :: Object ( sizes) )
284
+ Ok ( sizes)
286
285
}
287
286
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 ( ) ;
290
289
291
290
m. insert ( "100M_tcp" . to_string ( ) , throughput:: tcp ( deno_exe, 100 ) ?) ;
292
291
m. insert ( "100M_cat" . to_string ( ) , throughput:: cat ( deno_exe, 100 ) ?) ;
293
292
m. insert ( "10M_tcp" . to_string ( ) , throughput:: tcp ( deno_exe, 10 ) ?) ;
294
293
m. insert ( "10M_cat" . to_string ( ) , throughput:: cat ( deno_exe, 10 ) ?) ;
295
294
296
- Ok ( Value :: Object ( m ) )
295
+ Ok ( m )
297
296
}
298
297
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 < ( ) > {
303
299
let stats = http:: benchmark ( target_dir) ?;
304
300
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 ( ) ;
316
305
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 ( ) ;
331
310
332
311
Ok ( ( ) )
333
312
}
334
313
335
314
fn run_strace_benchmarks (
336
315
deno_exe : & PathBuf ,
337
- new_data : & mut Map < String , Value > ,
316
+ new_data : & mut BenchResult ,
338
317
) -> Result < ( ) > {
339
318
use std:: io:: Read ;
340
319
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 ( ) ;
343
322
344
323
for ( name, args, _) in EXEC_TIME_BENCHMARKS {
345
324
let mut file = tempfile:: NamedTempFile :: new ( ) ?;
@@ -361,26 +340,20 @@ fn run_strace_benchmarks(
361
340
file. as_file_mut ( ) . read_to_string ( & mut output) ?;
362
341
363
342
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) ;
374
347
}
375
348
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;
378
351
379
352
Ok ( ( ) )
380
353
}
381
354
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 ( ) ;
384
357
385
358
for ( name, args, return_code) in EXEC_TIME_BENCHMARKS {
386
359
let proc = Command :: new ( "time" )
@@ -396,13 +369,10 @@ fn run_max_mem_benchmark(deno_exe: &PathBuf) -> Result<Value> {
396
369
}
397
370
let out = String :: from_utf8 ( proc_result. stderr ) ?;
398
371
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 ( ) ) ;
403
373
}
404
374
405
- Ok ( Value :: Object ( results) )
375
+ Ok ( results)
406
376
}
407
377
408
378
fn cargo_deps ( ) -> usize {
@@ -420,6 +390,44 @@ fn cargo_deps() -> usize {
420
390
count
421
391
}
422
392
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
+
423
431
/*
424
432
TODO(SyrupThinker)
425
433
Switch to the #[bench] attribute once
@@ -439,60 +447,43 @@ fn main() -> Result<()> {
439
447
440
448
env:: set_current_dir ( & test_util:: root_path ( ) ) ?;
441
449
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 ( ) ;
468
463
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) ?;
476
468
477
469
// Cannot run throughput benchmark on windows because they don't have nc or
478
470
// pipe.
479
471
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) ?;
481
473
run_http ( & target_dir, & mut new_data) ?;
482
474
}
483
475
484
476
if cfg ! ( target_os = "linux" ) {
485
477
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) ?;
488
479
}
489
480
490
481
println ! ( "===== <BENCHMARK RESULTS>" ) ;
491
482
serde_json:: to_writer_pretty ( std:: io:: stdout ( ) , & new_data) ?;
492
483
println ! ( "\n ===== </BENCHMARK RESULTS>" ) ;
493
484
494
485
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) ? ) ?;
496
487
} else {
497
488
eprintln ! ( "Cannot write bench.json, path is invalid" ) ;
498
489
}
0 commit comments