@@ -263,10 +263,12 @@ impl Benchmark {
263
263
}
264
264
265
265
eprintln ! ( "Preparing {}" , self . name) ;
266
- let profile_dirs = profiles
267
- . iter ( )
268
- . map ( |profile| Ok ( ( * profile, self . make_temp_dir ( & self . path ) ?) ) )
269
- . collect :: < anyhow:: Result < Vec < _ > > > ( ) ?;
266
+ let mut target_dirs: Vec < ( ( CodegenBackend , Profile ) , TempDir ) > = vec ! [ ] ;
267
+ for backend in backends {
268
+ for profile in & profiles {
269
+ target_dirs. push ( ( ( * backend, * profile) , self . make_temp_dir ( & self . path ) ?) ) ;
270
+ }
271
+ }
270
272
271
273
// In parallel (but with a limit to the number of CPUs), prepare all
272
274
// profiles. This is done in parallel vs. sequentially because:
@@ -290,22 +292,22 @@ impl Benchmark {
290
292
// to do this in Cargo today. We would also ideally build in the same
291
293
// target directory, but that's also not possible, as Cargo takes a
292
294
// target-directory global lock during compilation.
295
+ //
296
+ // To avoid potential problems with recompilations, artifacts compiled by
297
+ // different codegen backends are stored in separate directories.
293
298
let preparation_start = std:: time:: Instant :: now ( ) ;
294
299
std:: thread:: scope :: < _ , anyhow:: Result < ( ) > > ( |s| {
295
300
let server = jobserver:: Client :: new ( num_cpus:: get ( ) ) . context ( "jobserver::new" ) ?;
296
- let mut threads = Vec :: with_capacity ( profile_dirs . len ( ) ) ;
297
- for ( profile, prep_dir) in & profile_dirs {
301
+ let mut threads = Vec :: with_capacity ( target_dirs . len ( ) ) ;
302
+ for ( ( backend , profile) , prep_dir) in & target_dirs {
298
303
let server = server. clone ( ) ;
299
304
let thread = s. spawn :: < _ , anyhow:: Result < ( ) > > ( move || {
300
305
wait_for_future ( async move {
301
- // Prepare all backend artifacts into the same target directory
302
- for backend in backends {
303
- let server = server. clone ( ) ;
304
- self . mk_cargo_process ( toolchain, prep_dir. path ( ) , * profile, * backend)
305
- . jobserver ( server)
306
- . run_rustc ( false )
307
- . await ?;
308
- }
306
+ let server = server. clone ( ) ;
307
+ self . mk_cargo_process ( toolchain, prep_dir. path ( ) , * profile, * backend)
308
+ . jobserver ( server)
309
+ . run_rustc ( false )
310
+ . await ?;
309
311
Ok :: < ( ) , anyhow:: Error > ( ( ) )
310
312
} ) ?;
311
313
Ok ( ( ) )
@@ -331,88 +333,82 @@ impl Benchmark {
331
333
) ;
332
334
333
335
let benchmark_start = std:: time:: Instant :: now ( ) ;
334
- for & backend in backends {
335
- for ( profile, prep_dir) in & profile_dirs {
336
- let profile = * profile;
337
- eprintln ! (
338
- "Running {}: {:?} + {:?} + {:?}" ,
339
- self . name, profile, scenarios, backend
340
- ) ;
336
+ for ( ( backend, profile) , prep_dir) in & target_dirs {
337
+ let backend = * backend;
338
+ let profile = * profile;
339
+ eprintln ! (
340
+ "Running {}: {:?} + {:?} + {:?}" ,
341
+ self . name, profile, scenarios, backend
342
+ ) ;
343
+
344
+ // We want at least two runs for all benchmarks (since we run
345
+ // self-profile separately).
346
+ processor. start_first_collection ( ) ;
347
+ for i in 0 ..std:: cmp:: max ( iterations, 2 ) {
348
+ if i == 1 {
349
+ let different = processor. finished_first_collection ( ) ;
350
+ if iterations == 1 && !different {
351
+ // Don't run twice if this processor doesn't need it and
352
+ // we've only been asked to run once.
353
+ break ;
354
+ }
355
+ }
356
+ log:: debug!( "Benchmark iteration {}/{}" , i + 1 , iterations) ;
357
+ // Don't delete the directory on error.
358
+ let timing_dir = ManuallyDrop :: new ( self . make_temp_dir ( prep_dir. path ( ) ) ?) ;
359
+ let cwd = timing_dir. path ( ) ;
360
+
361
+ // A full non-incremental build.
362
+ if scenarios. contains ( & Scenario :: Full ) {
363
+ self . mk_cargo_process ( toolchain, cwd, profile, backend)
364
+ . processor ( processor, Scenario :: Full , "Full" , None )
365
+ . run_rustc ( true )
366
+ . await ?;
367
+ }
341
368
342
- // We want at least two runs for all benchmarks (since we run
343
- // self-profile separately).
344
- processor. start_first_collection ( ) ;
345
- for i in 0 ..std:: cmp:: max ( iterations, 2 ) {
346
- if i == 1 {
347
- let different = processor. finished_first_collection ( ) ;
348
- if iterations == 1 && !different {
349
- // Don't run twice if this processor doesn't need it and
350
- // we've only been asked to run once.
351
- break ;
352
- }
369
+ // Rustdoc does not support incremental compilation
370
+ if profile != Profile :: Doc {
371
+ // An incremental from scratch (slowest incremental case).
372
+ // This is required for any subsequent incremental builds.
373
+ if scenarios. iter ( ) . any ( |s| s. is_incr ( ) ) {
374
+ self . mk_cargo_process ( toolchain, cwd, profile, backend)
375
+ . incremental ( true )
376
+ . processor ( processor, Scenario :: IncrFull , "IncrFull" , None )
377
+ . run_rustc ( true )
378
+ . await ?;
353
379
}
354
- log:: debug!( "Benchmark iteration {}/{}" , i + 1 , iterations) ;
355
- // Don't delete the directory on error.
356
- let timing_dir = ManuallyDrop :: new ( self . make_temp_dir ( prep_dir. path ( ) ) ?) ;
357
- let cwd = timing_dir. path ( ) ;
358
380
359
- // A full non- incremental build.
360
- if scenarios. contains ( & Scenario :: Full ) {
381
+ // An incremental build with no changes (fastest incremental case) .
382
+ if scenarios. contains ( & Scenario :: IncrUnchanged ) {
361
383
self . mk_cargo_process ( toolchain, cwd, profile, backend)
362
- . processor ( processor, Scenario :: Full , "Full" , None )
384
+ . incremental ( true )
385
+ . processor ( processor, Scenario :: IncrUnchanged , "IncrUnchanged" , None )
363
386
. run_rustc ( true )
364
387
. await ?;
365
388
}
366
389
367
- // Rustdoc does not support incremental compilation
368
- if profile != Profile :: Doc {
369
- // An incremental from scratch (slowest incremental case).
370
- // This is required for any subsequent incremental builds.
371
- if scenarios. iter ( ) . any ( |s| s. is_incr ( ) ) {
372
- self . mk_cargo_process ( toolchain, cwd, profile, backend)
373
- . incremental ( true )
374
- . processor ( processor, Scenario :: IncrFull , "IncrFull" , None )
375
- . run_rustc ( true )
376
- . await ?;
377
- }
390
+ if scenarios. contains ( & Scenario :: IncrPatched ) {
391
+ for ( i, patch) in self . patches . iter ( ) . enumerate ( ) {
392
+ log:: debug!( "applying patch {}" , patch. name) ;
393
+ patch. apply ( cwd) . map_err ( |s| anyhow:: anyhow!( "{}" , s) ) ?;
378
394
379
- // An incremental build with no changes (fastest incremental case).
380
- if scenarios. contains ( & Scenario :: IncrUnchanged ) {
395
+ // An incremental build with some changes (realistic
396
+ // incremental case).
397
+ let scenario_str = format ! ( "IncrPatched{}" , i) ;
381
398
self . mk_cargo_process ( toolchain, cwd, profile, backend)
382
399
. incremental ( true )
383
400
. processor (
384
401
processor,
385
- Scenario :: IncrUnchanged ,
386
- "IncrUnchanged" ,
387
- None ,
402
+ Scenario :: IncrPatched ,
403
+ & scenario_str ,
404
+ Some ( patch ) ,
388
405
)
389
406
. run_rustc ( true )
390
407
. await ?;
391
408
}
392
-
393
- if scenarios. contains ( & Scenario :: IncrPatched ) {
394
- for ( i, patch) in self . patches . iter ( ) . enumerate ( ) {
395
- log:: debug!( "applying patch {}" , patch. name) ;
396
- patch. apply ( cwd) . map_err ( |s| anyhow:: anyhow!( "{}" , s) ) ?;
397
-
398
- // An incremental build with some changes (realistic
399
- // incremental case).
400
- let scenario_str = format ! ( "IncrPatched{}" , i) ;
401
- self . mk_cargo_process ( toolchain, cwd, profile, backend)
402
- . incremental ( true )
403
- . processor (
404
- processor,
405
- Scenario :: IncrPatched ,
406
- & scenario_str,
407
- Some ( patch) ,
408
- )
409
- . run_rustc ( true )
410
- . await ?;
411
- }
412
- }
413
409
}
414
- drop ( ManuallyDrop :: into_inner ( timing_dir) ) ;
415
410
}
411
+ drop ( ManuallyDrop :: into_inner ( timing_dir) ) ;
416
412
}
417
413
}
418
414
log:: trace!(
0 commit comments