11use super :: helpers:: validate_walltime_results;
22use super :: isolation:: wrap_with_isolation;
3- use super :: profiler:: perf:: PerfRunner ;
3+ use super :: profiler:: Profiler ;
4+ use super :: profiler:: perf:: PerfProfiler ;
45use crate :: executor:: Executor ;
56use crate :: executor:: ExecutorConfig ;
67use crate :: executor:: ToolStatus ;
78use crate :: executor:: helpers:: command:: CommandBuilder ;
89use crate :: executor:: helpers:: env:: { build_path_env, get_base_injected_env} ;
910use crate :: executor:: helpers:: get_bench_command:: get_bench_command;
1011use crate :: executor:: helpers:: run_command_with_log_pipe:: run_command_with_log_pipe;
12+ use crate :: executor:: helpers:: run_command_with_log_pipe:: run_command_with_log_pipe_and_callback;
1113use crate :: executor:: helpers:: run_with_env:: wrap_with_env;
1214use crate :: executor:: helpers:: run_with_sudo:: wrap_with_sudo;
15+ use crate :: executor:: shared:: fifo:: RunnerFifo ;
1316use crate :: executor:: { ExecutionContext , ExecutorName , ExecutorSupport } ;
1417use crate :: instruments:: mongo_tracer:: MongoTracer ;
1518use crate :: prelude:: * ;
1619use crate :: runner_mode:: RunnerMode ;
1720use crate :: system:: { SupportedOs , SystemInfo } ;
1821use async_trait:: async_trait;
22+ use runner_shared:: fifo:: Command as FifoCommand ;
23+ use runner_shared:: fifo:: IntegrationMode ;
1924use std:: fs:: canonicalize;
2025use std:: io:: Write ;
2126use std:: path:: Path ;
@@ -72,14 +77,17 @@ impl Drop for HookScriptsGuard {
7277}
7378
7479pub struct WallTimeExecutor {
75- perf : Option < PerfRunner > ,
80+ profiler : Option < Box < dyn Profiler > > ,
7681}
7782
7883impl WallTimeExecutor {
7984 pub fn new ( ) -> Self {
80- Self {
81- perf : cfg ! ( target_os = "linux" ) . then ( PerfRunner :: new) ,
82- }
85+ let profiler: Option < Box < dyn Profiler > > = if cfg ! ( target_os = "linux" ) {
86+ Some ( Box :: new ( PerfProfiler :: new ( ) ) )
87+ } else {
88+ None
89+ } ;
90+ Self { profiler }
8391 }
8492
8593 fn walltime_bench_cmd (
@@ -122,9 +130,7 @@ impl Executor for WallTimeExecutor {
122130 }
123131
124132 fn tool_status ( & self ) -> Option < ToolStatus > {
125- self . perf
126- . as_ref ( )
127- . map ( |_| super :: profiler:: perf:: setup:: get_perf_status ( ) )
133+ self . profiler . as_ref ( ) . and_then ( |p| p. tool_status ( ) )
128134 }
129135
130136 fn support_level ( & self , system_info : & SystemInfo ) -> ExecutorSupport {
@@ -136,33 +142,33 @@ impl Executor for WallTimeExecutor {
136142 }
137143
138144 async fn setup ( & self , system_info : & SystemInfo , setup_cache_dir : Option < & Path > ) -> Result < ( ) > {
139- if self . perf . is_some ( ) {
140- return PerfRunner :: setup_environment ( system_info, setup_cache_dir) . await ;
145+ if let Some ( profiler ) = & self . profiler {
146+ profiler . setup ( system_info, setup_cache_dir) . await ? ;
141147 }
142-
143148 Ok ( ( ) )
144149 }
145150
146151 async fn run (
147- & self ,
152+ & mut self ,
148153 execution_context : & ExecutionContext ,
149154 _mongo_tracer : & Option < MongoTracer > ,
150155 ) -> Result < ( ) > {
151- let status = {
152- let _guard = HookScriptsGuard :: setup ( ) ;
153-
154- let ( _env_file , _script_file , cmd_builder ) =
155- WallTimeExecutor :: walltime_bench_cmd ( & execution_context . config , execution_context ) ? ;
156- if let Some ( perf ) = & self . perf
157- && execution_context. config . enable_perf
158- {
159- perf . run (
156+ let _guard = HookScriptsGuard :: setup ( ) ;
157+
158+ let ( _env_file , _script_file , cmd_builder ) =
159+ WallTimeExecutor :: walltime_bench_cmd ( & execution_context . config , execution_context ) ? ;
160+
161+ let status = match self . profiler . as_mut ( ) {
162+ Some ( profiler ) if execution_context. config . enable_perf => {
163+ run_with_profiler (
164+ profiler . as_mut ( ) ,
160165 cmd_builder,
161166 & execution_context. config ,
162167 & execution_context. profile_folder ,
163168 )
164169 . await
165- } else {
170+ }
171+ _ => {
166172 let cmd_builder = if cfg ! ( target_os = "linux" ) {
167173 wrap_with_sudo ( cmd_builder) ?
168174 } else {
@@ -187,13 +193,6 @@ impl Executor for WallTimeExecutor {
187193 async fn teardown ( & self , execution_context : & ExecutionContext ) -> Result < ( ) > {
188194 debug ! ( "Copying files to the profile folder" ) ;
189195
190- if let Some ( perf) = & self . perf
191- && execution_context. config . enable_perf
192- {
193- perf. save_files_to ( & execution_context. profile_folder )
194- . await ?;
195- }
196-
197196 validate_walltime_results (
198197 & execution_context. profile_folder ,
199198 execution_context. config . allow_empty ,
@@ -203,6 +202,55 @@ impl Executor for WallTimeExecutor {
203202 }
204203}
205204
205+ /// Drive a single benchmark run through a [`Profiler`]: wrap the command,
206+ /// spawn it, dispatch FIFO commands from the integration into the profiler's
207+ /// hooks, and finalize once the child exits.
208+ async fn run_with_profiler (
209+ profiler : & mut dyn Profiler ,
210+ cmd_builder : CommandBuilder ,
211+ config : & ExecutorConfig ,
212+ profile_folder : & Path ,
213+ ) -> Result < std:: process:: ExitStatus > {
214+ let wrapped = profiler. wrap ( cmd_builder, config, profile_folder) . await ?;
215+ let cmd = wrapped. build ( ) ;
216+ debug ! ( "cmd: {cmd:?}" ) ;
217+
218+ let mut runner_fifo = RunnerFifo :: new ( ) ?;
219+
220+ run_command_with_log_pipe_and_callback ( cmd, async move |mut child| {
221+ let on_cmd = async |c : & FifoCommand | match c {
222+ FifoCommand :: StartBenchmark => {
223+ profiler. on_start_benchmark ( ) . await ?;
224+ Ok ( None )
225+ }
226+ FifoCommand :: StopBenchmark => {
227+ profiler. on_stop_benchmark ( ) . await ?;
228+ Ok ( None )
229+ }
230+ #[ allow( deprecated) ]
231+ FifoCommand :: PingProfiler => Ok ( Some ( if profiler. on_ping ( ) . await ? {
232+ FifoCommand :: Ack
233+ } else {
234+ FifoCommand :: Err
235+ } ) ) ,
236+ FifoCommand :: GetIntegrationMode => Ok ( Some ( FifoCommand :: IntegrationModeResponse (
237+ IntegrationMode :: Walltime ,
238+ ) ) ) ,
239+ _ => Ok ( None ) ,
240+ } ;
241+
242+ let ( timestamps, fifo_data, exit_status) =
243+ runner_fifo. handle_fifo_messages ( & mut child, on_cmd) . await ?;
244+
245+ profiler
246+ . finalize ( fifo_data, timestamps, profile_folder)
247+ . await ?;
248+
249+ Ok ( exit_status)
250+ } )
251+ . await
252+ }
253+
206254#[ cfg( test) ]
207255mod tests {
208256 use tempfile:: NamedTempFile ;
0 commit comments