@@ -59,7 +59,7 @@ use collector::toolchain::{
5959} ;
6060use collector:: utils:: cachegrind:: cachegrind_diff;
6161use collector:: utils:: { is_installed, wait_for_future} ;
62- use collector:: { utils, CollectorCtx , CollectorStepBuilder } ;
62+ use collector:: { command_output , utils, CollectorCtx , CollectorStepBuilder } ;
6363use database:: {
6464 ArtifactId , ArtifactIdNumber , BenchmarkJob , BenchmarkJobConclusion , CollectorConfig , Commit ,
6565 CommitType , Connection , Pool ,
@@ -708,6 +708,16 @@ enum Commands {
708708 #[ arg( long) ]
709709 collector_name : String ,
710710
711+ /// Git SHA of the commit that the collector is currently on.
712+ /// If not present, the collector will attempt to figure it out from git directly.
713+ #[ arg( long) ]
714+ git_sha : Option < String > ,
715+
716+ /// Periodically check if the collector's commit SHA matches the commit SHA of the
717+ /// rustc-perf repository.
718+ #[ arg( long) ]
719+ check_git_sha : bool ,
720+
711721 #[ command( flatten) ]
712722 db : DbOption ,
713723 } ,
@@ -1352,17 +1362,34 @@ Make sure to modify `{dir}/perf-config.json` if the category/artifact don't matc
13521362 Ok ( 0 )
13531363 }
13541364
1355- Commands :: BenchmarkJobQueue { collector_name, db } => {
1365+ Commands :: BenchmarkJobQueue {
1366+ collector_name,
1367+ git_sha,
1368+ check_git_sha,
1369+ db,
1370+ } => {
13561371 log_db ( & db) ;
13571372
1373+ let git_sha = match git_sha {
1374+ Some ( sha) => sha,
1375+ None => {
1376+ let mut cmd = Command :: new ( "git" ) ;
1377+ cmd. args ( [ "rev-parse" , "HEAD" ] ) ;
1378+ let stdout = command_output ( & mut cmd)
1379+ . context ( "Cannot determine current commit SHA" ) ?
1380+ . stdout ;
1381+ String :: from_utf8 ( stdout) . unwrap ( ) . trim ( ) . to_string ( )
1382+ }
1383+ } ;
1384+
13581385 let pool = Pool :: open ( & db. db ) ;
13591386 let rt = build_async_runtime ( ) ;
13601387 let conn = rt. block_on ( pool. connection ( ) ) ;
13611388
13621389 // Obtain the configuration and validate that it matches the
13631390 // collector's host target
13641391 let collector_config = rt
1365- . block_on ( conn. get_collector_config ( & collector_name) ) ?
1392+ . block_on ( conn. start_collector ( & collector_name, & git_sha ) ) ?
13661393 . ok_or_else ( || {
13671394 anyhow:: anyhow!( "Collector with name `{collector_name}` not found" )
13681395 } ) ?;
@@ -1374,6 +1401,13 @@ Make sure to modify `{dir}/perf-config.json` if the category/artifact don't matc
13741401 ) ) ;
13751402 }
13761403
1404+ log:: info!(
1405+ "Starting collector with target {}, benchmark set {} and commit {}" ,
1406+ collector_config. target( ) ,
1407+ collector_config. benchmark_set( ) . get_id( ) ,
1408+ collector_config. commit_sha( ) . expect( "missing commit SHA" )
1409+ ) ;
1410+
13771411 let benchmarks =
13781412 get_compile_benchmarks ( & compile_benchmark_dir, CompileBenchmarkFilter :: All ) ?;
13791413
@@ -1382,6 +1416,7 @@ Make sure to modify `{dir}/perf-config.json` if the category/artifact don't matc
13821416 conn,
13831417 & collector_config,
13841418 benchmarks,
1419+ check_git_sha,
13851420 ) ) ?;
13861421
13871422 Ok ( 0 )
@@ -1397,10 +1432,10 @@ async fn run_job_queue_benchmarks(
13971432 mut conn : Box < dyn Connection > ,
13981433 collector : & CollectorConfig ,
13991434 all_compile_benchmarks : Vec < Benchmark > ,
1435+ check_git_sha : bool ,
14001436) -> anyhow:: Result < ( ) > {
1401- conn . update_collector_heartbeat ( collector . name ( ) ) . await ? ;
1437+ let mut last_request_tag = None ;
14021438
1403- // TODO: check collector SHA vs site SHA
14041439 while let Some ( ( benchmark_job, artifact_id) ) = conn
14051440 . dequeue_benchmark_job (
14061441 collector. name ( ) ,
@@ -1409,6 +1444,22 @@ async fn run_job_queue_benchmarks(
14091444 )
14101445 . await ?
14111446 {
1447+ // Here we check if we should update our commit SHA, if rustc-perf has been updated.
1448+ // We only check for updates when we switch *benchmark requests*, not *benchmark jobs*,
1449+ // to avoid changing code in the middle of benchmarking the same request.
1450+ // Note that if an update happens, the job that we have just dequeued will have its deque
1451+ // counter increased. But since updates are relatively rare, that shouldn't be a big deal,
1452+ // it will be dequeued again when the collector starts again.
1453+ if check_git_sha
1454+ && last_request_tag. is_some ( )
1455+ && last_request_tag. as_deref ( ) != Some ( benchmark_job. request_tag ( ) )
1456+ && needs_git_update ( collector)
1457+ {
1458+ log:: warn!( "Exiting collector to update itself from git." ) ;
1459+ return Ok ( ( ) ) ;
1460+ }
1461+ last_request_tag = Some ( benchmark_job. request_tag ( ) . to_string ( ) ) ;
1462+
14121463 log:: info!( "Dequeued job {benchmark_job:?}, artifact_id {artifact_id:?}" ) ;
14131464 let result = run_benchmark_job (
14141465 conn. as_mut ( ) ,
@@ -1472,6 +1523,39 @@ async fn run_job_queue_benchmarks(
14721523 Ok ( ( ) )
14731524}
14741525
1526+ /// Returns true if the commit SHA of collector does not match the latest commit SHA of the master
1527+ /// branch of https://github.com/rust-lang/rustc-perf.
1528+ fn needs_git_update ( collector : & CollectorConfig ) -> bool {
1529+ let Some ( commit_sha) = collector. commit_sha ( ) else {
1530+ return false ;
1531+ } ;
1532+
1533+ let mut cmd = Command :: new ( "git" ) ;
1534+ cmd. arg ( "ls-remote" )
1535+ . arg ( "https://github.com/rust-lang/rustc-perf" )
1536+ . arg ( "HEAD" ) ;
1537+ let upstream_sha = match command_output ( & mut cmd) {
1538+ Ok ( output) => String :: from_utf8 ( output. stdout )
1539+ . unwrap ( )
1540+ . split_whitespace ( )
1541+ . next ( )
1542+ . unwrap ( )
1543+ . to_string ( ) ,
1544+ Err ( error) => {
1545+ log:: error!( "Cannot determine latest SHA of rustc-perf: {error:?}" ) ;
1546+ return false ;
1547+ }
1548+ } ;
1549+ if commit_sha != upstream_sha {
1550+ log:: warn!(
1551+ "Commit {commit_sha} of collector is outdated, latest commit is {upstream_sha}."
1552+ ) ;
1553+ true
1554+ } else {
1555+ false
1556+ }
1557+ }
1558+
14751559/// Error that happened during benchmarking of a job.
14761560enum BenchmarkJobError {
14771561 /// The error is non-recoverable.
0 commit comments