@@ -8,6 +8,7 @@ use crate::compile::execute::{CargoProcess, Processor};
8
8
use crate :: toolchain:: Toolchain ;
9
9
use crate :: utils:: wait_for_future;
10
10
use anyhow:: { bail, Context } ;
11
+ use database:: selector:: CompileTestCase ;
11
12
use log:: debug;
12
13
use std:: collections:: { HashMap , HashSet } ;
13
14
use std:: fmt:: { Display , Formatter } ;
@@ -249,6 +250,7 @@ impl Benchmark {
249
250
toolchain : & Toolchain ,
250
251
iterations : Option < usize > ,
251
252
targets : & [ Target ] ,
253
+ already_computed : & hashbrown:: HashSet < CompileTestCase > ,
252
254
) -> anyhow:: Result < ( ) > {
253
255
if self . config . disabled {
254
256
eprintln ! ( "Skipping {}: disabled" , self . name) ;
@@ -279,19 +281,62 @@ impl Benchmark {
279
281
return Ok ( ( ) ) ;
280
282
}
281
283
282
- eprintln ! ( "Preparing {}" , self . name) ;
283
- let mut target_dirs: Vec < ( ( CodegenBackend , Profile , Target ) , TempDir ) > = vec ! [ ] ;
284
+ struct BenchmarkDir {
285
+ dir : TempDir ,
286
+ scenarios : HashSet < Scenario > ,
287
+ profile : Profile ,
288
+ backend : CodegenBackend ,
289
+ target : Target ,
290
+ }
291
+
292
+ // Materialize the test cases that we want to benchmark
293
+ // We need to handle scenarios a bit specially, because they share the target directory
294
+ let mut benchmark_dirs: Vec < BenchmarkDir > = vec ! [ ] ;
295
+
284
296
for backend in backends {
285
297
for profile in & profiles {
286
298
for target in targets {
287
- target_dirs. push ( (
288
- ( * backend, * profile, * target) ,
289
- self . make_temp_dir ( & self . path ) ?,
290
- ) ) ;
299
+ // Do we have any scenarios left to compute?
300
+ let remaining_scenarios = scenarios
301
+ . iter ( )
302
+ . flat_map ( |scenario| {
303
+ self . create_test_cases ( scenario, profile, backend, target)
304
+ . into_iter ( )
305
+ . map ( |test_case| ( * scenario, test_case) )
306
+ } )
307
+ . filter ( |( _, test_case) | !already_computed. contains ( test_case) )
308
+ . map ( |( scenario, _) | scenario)
309
+ . collect :: < HashSet < Scenario > > ( ) ;
310
+ if remaining_scenarios. is_empty ( ) {
311
+ continue ;
312
+ }
313
+
314
+ let temp_dir = self . make_temp_dir ( & self . path ) ?;
315
+ benchmark_dirs. push ( BenchmarkDir {
316
+ dir : temp_dir,
317
+ scenarios : remaining_scenarios,
318
+ profile : * profile,
319
+ backend : * backend,
320
+ target : * target,
321
+ } ) ;
291
322
}
292
323
}
293
324
}
294
325
326
+ if benchmark_dirs. is_empty ( ) {
327
+ eprintln ! (
328
+ "Skipping {}: all test cases were previously computed" ,
329
+ self . name
330
+ ) ;
331
+ return Ok ( ( ) ) ;
332
+ }
333
+
334
+ eprintln ! (
335
+ "Preparing {} (test cases: {})" ,
336
+ self . name,
337
+ benchmark_dirs. len( )
338
+ ) ;
339
+
295
340
// In parallel (but with a limit to the number of CPUs), prepare all
296
341
// profiles. This is done in parallel vs. sequentially because:
297
342
// * We don't record any measurements during this phase, so the
@@ -325,18 +370,18 @@ impl Benchmark {
325
370
. get ( ) ,
326
371
)
327
372
. context ( "jobserver::new" ) ?;
328
- let mut threads = Vec :: with_capacity ( target_dirs . len ( ) ) ;
329
- for ( ( backend , profile , target ) , prep_dir ) in & target_dirs {
373
+ let mut threads = Vec :: with_capacity ( benchmark_dirs . len ( ) ) ;
374
+ for benchmark_dir in & benchmark_dirs {
330
375
let server = server. clone ( ) ;
331
376
let thread = s. spawn :: < _ , anyhow:: Result < ( ) > > ( move || {
332
377
wait_for_future ( async move {
333
378
let server = server. clone ( ) ;
334
379
self . mk_cargo_process (
335
380
toolchain,
336
- prep_dir . path ( ) ,
337
- * profile,
338
- * backend,
339
- * target,
381
+ benchmark_dir . dir . path ( ) ,
382
+ benchmark_dir . profile ,
383
+ benchmark_dir . backend ,
384
+ benchmark_dir . target ,
340
385
)
341
386
. jobserver ( server)
342
387
. run_rustc ( false )
@@ -371,10 +416,11 @@ impl Benchmark {
371
416
let mut timing_dirs: Vec < ManuallyDrop < TempDir > > = vec ! [ ] ;
372
417
373
418
let benchmark_start = std:: time:: Instant :: now ( ) ;
374
- for ( ( backend, profile, target) , prep_dir) in & target_dirs {
375
- let backend = * backend;
376
- let profile = * profile;
377
- let target = * target;
419
+ for benchmark_dir in & benchmark_dirs {
420
+ let backend = benchmark_dir. backend ;
421
+ let profile = benchmark_dir. profile ;
422
+ let target = benchmark_dir. target ;
423
+ let scenarios = & benchmark_dir. scenarios ;
378
424
eprintln ! (
379
425
"Running {}: {:?} + {:?} + {:?} + {:?}" ,
380
426
self . name, profile, scenarios, backend, target,
@@ -394,7 +440,7 @@ impl Benchmark {
394
440
}
395
441
log:: debug!( "Benchmark iteration {}/{}" , i + 1 , iterations) ;
396
442
// Don't delete the directory on error.
397
- let timing_dir = ManuallyDrop :: new ( self . make_temp_dir ( prep_dir . path ( ) ) ?) ;
443
+ let timing_dir = ManuallyDrop :: new ( self . make_temp_dir ( benchmark_dir . dir . path ( ) ) ?) ;
398
444
let cwd = timing_dir. path ( ) ;
399
445
400
446
// A full non-incremental build.
@@ -464,6 +510,42 @@ impl Benchmark {
464
510
465
511
Ok ( ( ) )
466
512
}
513
+
514
+ fn create_test_cases (
515
+ & self ,
516
+ scenario : & Scenario ,
517
+ profile : & Profile ,
518
+ backend : & CodegenBackend ,
519
+ target : & Target ,
520
+ ) -> Vec < CompileTestCase > {
521
+ self . patches
522
+ . iter ( )
523
+ . map ( |patch| CompileTestCase {
524
+ benchmark : database:: Benchmark :: from ( self . name . 0 . as_str ( ) ) ,
525
+ profile : match profile {
526
+ Profile :: Check => database:: Profile :: Check ,
527
+ Profile :: Debug => database:: Profile :: Debug ,
528
+ Profile :: Doc => database:: Profile :: Doc ,
529
+ Profile :: DocJson => database:: Profile :: DocJson ,
530
+ Profile :: Opt => database:: Profile :: Opt ,
531
+ Profile :: Clippy => database:: Profile :: Clippy ,
532
+ } ,
533
+ scenario : match scenario {
534
+ Scenario :: Full => database:: Scenario :: Empty ,
535
+ Scenario :: IncrFull => database:: Scenario :: IncrementalEmpty ,
536
+ Scenario :: IncrUnchanged => database:: Scenario :: IncrementalFresh ,
537
+ Scenario :: IncrPatched => database:: Scenario :: IncrementalPatch ( patch. name ) ,
538
+ } ,
539
+ backend : match backend {
540
+ CodegenBackend :: Llvm => database:: CodegenBackend :: Llvm ,
541
+ CodegenBackend :: Cranelift => database:: CodegenBackend :: Cranelift ,
542
+ } ,
543
+ target : match target {
544
+ Target :: X86_64UnknownLinuxGnu => database:: Target :: X86_64UnknownLinuxGnu ,
545
+ } ,
546
+ } )
547
+ . collect ( )
548
+ }
467
549
}
468
550
469
551
/// Directory containing compile-time benchmarks.
0 commit comments