11/* **********************************************************
2- * Copyright (c) 2016-2024 Google, Inc. All rights reserved.
2+ * Copyright (c) 2016-2025 Google, Inc. All rights reserved.
33 * **********************************************************/
44
55/*
@@ -229,13 +229,13 @@ analyzer_tmpl_t<RecordType, ReaderType>::analyzer_tmpl_t()
229229template <typename RecordType, typename ReaderType>
230230bool
231231analyzer_tmpl_t <RecordType, ReaderType>::init_scheduler(
232- const std::string &trace_path, const std::set< memref_tid_t > &only_threads ,
233- const std::set<int > &only_shards, int output_limit, int verbosity ,
234- typename sched_type_t ::scheduler_options_t options)
232+ const std::vector< std::string > &trace_paths ,
233+ const std::set<memref_tid_t > &only_threads, const std::set< int > &only_shards ,
234+ int output_limit, int verbosity, typename sched_type_t ::scheduler_options_t options)
235235{
236236 verbosity_ = verbosity;
237- if (trace_path .empty ()) {
238- ERRMSG (" Trace file name is empty \n " );
237+ if (trace_paths .empty ()) {
238+ ERRMSG (" Missing trace path(s) \n " );
239239 return false ;
240240 }
241241 std::vector<typename sched_type_t ::range_t > regions;
@@ -246,14 +246,24 @@ analyzer_tmpl_t<RecordType, ReaderType>::init_scheduler(
246246 // capability in the scheduler we should switch to that.
247247 regions.emplace_back (skip_instrs_ + 1 , 0 );
248248 }
249- typename sched_type_t ::input_workload_t workload (trace_path, regions);
250- workload.only_threads = only_threads;
251- workload.only_shards = only_shards;
252- workload.output_limit = output_limit;
253- if (regions.empty () && skip_to_timestamp_ > 0 ) {
254- workload.times_of_interest .emplace_back (skip_to_timestamp_, 0 );
249+ std::vector<typename sched_type_t ::input_workload_t > workloads;
250+ for (const std::string &path : trace_paths) {
251+ if (path.empty ()) {
252+ ERRMSG (" Trace path is empty\n " );
253+ return false ;
254+ }
255+ workloads.emplace_back (path, regions);
256+ // As documented and checked in analyzer_multi.cpp, only_threads and only_shards
257+ // limits are not supported with -multi_indir. That's already been checked, so
258+ // we do not perform additional checks here.
259+ workloads.back ().only_threads = only_threads;
260+ workloads.back ().only_shards = only_shards;
261+ workloads.back ().output_limit = output_limit;
262+ if (regions.empty () && skip_to_timestamp_ > 0 ) {
263+ workloads.back ().times_of_interest .emplace_back (skip_to_timestamp_, 0 );
264+ }
255265 }
256- return init_scheduler_common (workload , std::move (options));
266+ return init_scheduler_common (workloads , std::move (options));
257267}
258268
259269template <typename RecordType, typename ReaderType>
@@ -274,14 +284,15 @@ analyzer_tmpl_t<RecordType, ReaderType>::init_scheduler(
274284 std::vector<typename sched_type_t ::range_t > regions;
275285 if (skip_instrs_ > 0 )
276286 regions.emplace_back (skip_instrs_ + 1 , 0 );
277- typename sched_type_t ::input_workload_t workload (std::move (readers), regions);
278- return init_scheduler_common (workload, std::move (options));
287+ std::vector<typename sched_type_t ::input_workload_t > workloads;
288+ workloads.emplace_back (std::move (readers), regions);
289+ return init_scheduler_common (workloads, std::move (options));
279290}
280291
281292template <typename RecordType, typename ReaderType>
282293bool
283294analyzer_tmpl_t <RecordType, ReaderType>::init_scheduler_common(
284- typename sched_type_t ::input_workload_t &workload ,
295+ std::vector< typename sched_type_t ::input_workload_t > &workloads ,
285296 typename sched_type_t ::scheduler_options_t options)
286297{
287298 for (int i = 0 ; i < num_tools_; ++i) {
@@ -290,8 +301,6 @@ analyzer_tmpl_t<RecordType, ReaderType>::init_scheduler_common(
290301 break ;
291302 }
292303 }
293- std::vector<typename sched_type_t ::input_workload_t > sched_inputs (1 );
294- sched_inputs[0 ] = std::move (workload);
295304
296305 typename sched_type_t ::scheduler_options_t sched_ops;
297306 int output_count = worker_count_;
@@ -326,7 +335,7 @@ analyzer_tmpl_t<RecordType, ReaderType>::init_scheduler_common(
326335 output_count = 1 ;
327336 }
328337 sched_mapping_ = options.mapping ;
329- if (scheduler_.init (sched_inputs , output_count, std::move (sched_ops)) !=
338+ if (scheduler_.init (workloads , output_count, std::move (sched_ops)) !=
330339 sched_type_t ::STATUS_SUCCESS) {
331340 ERRMSG (" Failed to initialize scheduler: %s\n " ,
332341 scheduler_.get_error_string ().c_str ());
@@ -384,7 +393,7 @@ analyzer_tmpl_t<RecordType, ReaderType>::analyzer_tmpl_t(
384393 // The scheduler will call reader_t::init() for each input file. We assume
385394 // that won't block (analyzer_multi_t separates out IPC readers).
386395 typename sched_type_t ::scheduler_options_t sched_ops;
387- if (!init_scheduler (trace_path, {}, {}, /* output_limit=*/ 0 , verbosity,
396+ if (!init_scheduler ({ trace_path } , {}, {}, /* output_limit=*/ 0 , verbosity,
388397 std::move (sched_ops))) {
389398 success_ = false ;
390399 error_string_ = " Failed to create scheduler" ;
0 commit comments