@@ -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 } ;
@@ -243,6 +244,7 @@ impl Benchmark {
243
244
toolchain : & Toolchain ,
244
245
iterations : Option < usize > ,
245
246
targets : & [ Target ] ,
247
+ already_computed : & hashbrown:: HashSet < CompileTestCase > ,
246
248
) -> anyhow:: Result < ( ) > {
247
249
if self . config . disabled {
248
250
eprintln ! ( "Skipping {}: disabled" , self . name) ;
@@ -273,19 +275,62 @@ impl Benchmark {
273
275
return Ok ( ( ) ) ;
274
276
}
275
277
276
- eprintln ! ( "Preparing {}" , self . name) ;
277
- let mut target_dirs: Vec < ( ( CodegenBackend , Profile , Target ) , TempDir ) > = vec ! [ ] ;
278
+ struct BenchmarkDir {
279
+ dir : TempDir ,
280
+ scenarios : HashSet < Scenario > ,
281
+ profile : Profile ,
282
+ backend : CodegenBackend ,
283
+ target : Target ,
284
+ }
285
+
286
+ // Materialize the test cases that we want to benchmark
287
+ // We need to handle scenarios a bit specially, because they share the target directory
288
+ let mut benchmark_dirs: Vec < BenchmarkDir > = vec ! [ ] ;
289
+
278
290
for backend in backends {
279
291
for profile in & profiles {
280
292
for target in targets {
281
- target_dirs. push ( (
282
- ( * backend, * profile, * target) ,
283
- self . make_temp_dir ( & self . path ) ?,
284
- ) ) ;
293
+ // Do we have any scenarios left to compute?
294
+ let remaining_scenarios = scenarios
295
+ . iter ( )
296
+ . flat_map ( |scenario| {
297
+ self . create_test_cases ( scenario, profile, backend, target)
298
+ . into_iter ( )
299
+ . map ( |test_case| ( * scenario, test_case) )
300
+ } )
301
+ . filter ( |( _, test_case) | !already_computed. contains ( test_case) )
302
+ . map ( |( scenario, _) | scenario)
303
+ . collect :: < HashSet < Scenario > > ( ) ;
304
+ if remaining_scenarios. is_empty ( ) {
305
+ continue ;
306
+ }
307
+
308
+ let temp_dir = self . make_temp_dir ( & self . path ) ?;
309
+ benchmark_dirs. push ( BenchmarkDir {
310
+ dir : temp_dir,
311
+ scenarios : remaining_scenarios,
312
+ profile : * profile,
313
+ backend : * backend,
314
+ target : * target,
315
+ } ) ;
285
316
}
286
317
}
287
318
}
288
319
320
+ if benchmark_dirs. is_empty ( ) {
321
+ eprintln ! (
322
+ "Skipping {}: all test cases were previously computed" ,
323
+ self . name
324
+ ) ;
325
+ return Ok ( ( ) ) ;
326
+ }
327
+
328
+ eprintln ! (
329
+ "Preparing {} (test cases: {})" ,
330
+ self . name,
331
+ benchmark_dirs. len( )
332
+ ) ;
333
+
289
334
// In parallel (but with a limit to the number of CPUs), prepare all
290
335
// profiles. This is done in parallel vs. sequentially because:
291
336
// * We don't record any measurements during this phase, so the
@@ -319,18 +364,18 @@ impl Benchmark {
319
364
. get ( ) ,
320
365
)
321
366
. context ( "jobserver::new" ) ?;
322
- let mut threads = Vec :: with_capacity ( target_dirs . len ( ) ) ;
323
- for ( ( backend , profile , target ) , prep_dir ) in & target_dirs {
367
+ let mut threads = Vec :: with_capacity ( benchmark_dirs . len ( ) ) ;
368
+ for benchmark_dir in & benchmark_dirs {
324
369
let server = server. clone ( ) ;
325
370
let thread = s. spawn :: < _ , anyhow:: Result < ( ) > > ( move || {
326
371
wait_for_future ( async move {
327
372
let server = server. clone ( ) ;
328
373
self . mk_cargo_process (
329
374
toolchain,
330
- prep_dir . path ( ) ,
331
- * profile,
332
- * backend,
333
- * target,
375
+ benchmark_dir . dir . path ( ) ,
376
+ benchmark_dir . profile ,
377
+ benchmark_dir . backend ,
378
+ benchmark_dir . target ,
334
379
)
335
380
. jobserver ( server)
336
381
. run_rustc ( false )
@@ -365,10 +410,11 @@ impl Benchmark {
365
410
let mut timing_dirs: Vec < ManuallyDrop < TempDir > > = vec ! [ ] ;
366
411
367
412
let benchmark_start = std:: time:: Instant :: now ( ) ;
368
- for ( ( backend, profile, target) , prep_dir) in & target_dirs {
369
- let backend = * backend;
370
- let profile = * profile;
371
- let target = * target;
413
+ for benchmark_dir in & benchmark_dirs {
414
+ let backend = benchmark_dir. backend ;
415
+ let profile = benchmark_dir. profile ;
416
+ let target = benchmark_dir. target ;
417
+ let scenarios = & benchmark_dir. scenarios ;
372
418
eprintln ! (
373
419
"Running {}: {:?} + {:?} + {:?} + {:?}" ,
374
420
self . name, profile, scenarios, backend, target,
@@ -388,7 +434,7 @@ impl Benchmark {
388
434
}
389
435
log:: debug!( "Benchmark iteration {}/{}" , i + 1 , iterations) ;
390
436
// Don't delete the directory on error.
391
- let timing_dir = ManuallyDrop :: new ( self . make_temp_dir ( prep_dir . path ( ) ) ?) ;
437
+ let timing_dir = ManuallyDrop :: new ( self . make_temp_dir ( benchmark_dir . dir . path ( ) ) ?) ;
392
438
let cwd = timing_dir. path ( ) ;
393
439
394
440
// A full non-incremental build.
@@ -458,6 +504,42 @@ impl Benchmark {
458
504
459
505
Ok ( ( ) )
460
506
}
507
+
508
+ fn create_test_cases (
509
+ & self ,
510
+ scenario : & Scenario ,
511
+ profile : & Profile ,
512
+ backend : & CodegenBackend ,
513
+ target : & Target ,
514
+ ) -> Vec < CompileTestCase > {
515
+ self . patches
516
+ . iter ( )
517
+ . map ( |patch| CompileTestCase {
518
+ benchmark : database:: Benchmark :: from ( self . name . 0 . as_str ( ) ) ,
519
+ profile : match profile {
520
+ Profile :: Check => database:: Profile :: Check ,
521
+ Profile :: Debug => database:: Profile :: Debug ,
522
+ Profile :: Doc => database:: Profile :: Doc ,
523
+ Profile :: DocJson => database:: Profile :: DocJson ,
524
+ Profile :: Opt => database:: Profile :: Opt ,
525
+ Profile :: Clippy => database:: Profile :: Clippy ,
526
+ } ,
527
+ scenario : match scenario {
528
+ Scenario :: Full => database:: Scenario :: Empty ,
529
+ Scenario :: IncrFull => database:: Scenario :: IncrementalEmpty ,
530
+ Scenario :: IncrUnchanged => database:: Scenario :: IncrementalFresh ,
531
+ Scenario :: IncrPatched => database:: Scenario :: IncrementalPatch ( patch. name ) ,
532
+ } ,
533
+ backend : match backend {
534
+ CodegenBackend :: Llvm => database:: CodegenBackend :: Llvm ,
535
+ CodegenBackend :: Cranelift => database:: CodegenBackend :: Cranelift ,
536
+ } ,
537
+ target : match target {
538
+ Target :: X86_64UnknownLinuxGnu => database:: Target :: X86_64UnknownLinuxGnu ,
539
+ } ,
540
+ } )
541
+ . collect ( )
542
+ }
461
543
}
462
544
463
545
/// Directory containing compile-time benchmarks.
0 commit comments