Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
960dbbf
fix: Resolve Windows compilation error in binary_search type coercion
anthonyshew Feb 21, 2026
d996522
perf: Optimize engine builder, task visitor, and untracked file disco…
anthonyshew Feb 21, 2026
d5dfd6e
perf: Parallelize turbo run pre-execution hot path
anthonyshew Feb 22, 2026
af9d463
Merge branch 'main' of https://github.com/vercel/turborepo into perf/…
anthonyshew Feb 22, 2026
bf36bfa
fix: Remove dead code from Dependencies::new and DependencySplitter::…
anthonyshew Feb 22, 2026
b13977c
Merge branch 'main' of https://github.com/vercel/turborepo into perf/…
anthonyshew Feb 22, 2026
493073e
chore: Add tracing spans to previously uninstrumented hot path functions
anthonyshew Feb 22, 2026
0e826b1
Merge branch 'main' of https://github.com/vercel/turborepo into chore…
anthonyshew Feb 22, 2026
0739ca5
Merge branch 'main' of https://github.com/vercel/turborepo into chore…
anthonyshew Feb 22, 2026
c06149c
perf: Use Arc<str> for task dependency hashes to avoid heap clones
anthonyshew Feb 22, 2026
05de926
perf: Propagate Arc<str> through HashTrackerInfo trait and SharedTask…
anthonyshew Feb 22, 2026
33b8a84
fix: Explicitly enable serde/rc for Arc<str> serialization
anthonyshew Feb 22, 2026
8e216e4
Merge branch 'main' of https://github.com/vercel/turborepo into perf/…
anthonyshew Feb 22, 2026
7255ce8
perf: Add tracing spans across the entire turbo run startup path
anthonyshew Feb 23, 2026
c5972e1
fix: Use .instrument() instead of .entered() across await point
anthonyshew Feb 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions crates/turborepo-lib/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,17 +1298,24 @@ pub async fn run(
#[allow(unused_variables)] logger: &TurboSubscriber,
color_config: ColorConfig,
) -> Result<i32, Error> {
// TODO: remove mutability from this function
let mut cli_args = Args::new(env::args_os().collect());
let _cli_run_span = tracing::info_span!("cli_run").entered();

let mut cli_args = {
let _span = tracing::info_span!("cli_arg_parsing").entered();
Args::new(env::args_os().collect())
};
let version = get_version();

// Build a single HTTP client to share across telemetry, API, and cache
// operations. This avoids redundant TLS initialization (~150ms savings).
let http_client = APIClient::build_http_client(None)
.expect("Failed to create HTTP client: TLS initialization failed");
let http_client = {
let _span = tracing::info_span!("http_client_init").entered();
APIClient::build_http_client(None)
.expect("Failed to create HTTP client: TLS initialization failed")
};

// track telemetry handle to close at the end of the run
let telemetry_handle = initialize_telemetry_client(&http_client, color_config, version);
let telemetry_handle = {
let _span = tracing::info_span!("telemetry_init").entered();
initialize_telemetry_client(&http_client, color_config, version)
};

if should_print_version() {
eprintln!("{}", GREY.apply_to(format!("• turbo {}", get_version())));
Expand Down Expand Up @@ -1592,7 +1599,10 @@ pub async fn run(
let event = CommandEventBuilder::new("run").with_parent(&root_telemetry);
event.track_call();

let base = CommandBase::new(cli_args.clone(), repo_root, version, color_config)?;
let base = {
let _span = tracing::info_span!("command_base_new").entered();
CommandBase::new(cli_args.clone(), repo_root, version, color_config)?
};
event.track_ui_mode(base.opts.run_opts.ui_mode);

if execution_args.tasks.is_empty() {
Expand Down
10 changes: 8 additions & 2 deletions crates/turborepo-lib/src/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ pub async fn run(
let signal = get_signal()?;
let handler = SignalHandler::new(signal);

let run_builder = RunBuilder::new(base, Some(http_client))?;
let run_builder = {
let _span = tracing::info_span!("run_builder_new").entered();
RunBuilder::new(base, Some(http_client))?
};

let run_fut = async {
let (analytics_sender, analytics_handle) = run_builder.start_analytics();
Expand All @@ -27,7 +30,10 @@ pub async fn run(
.await?,
);

let (sender, handle) = run.start_ui()?.unzip();
let (sender, handle) = {
let _span = tracing::info_span!("start_ui").entered();
run.start_ui()?.unzip()
};

let result = run.run(sender.clone(), false).await;

Expand Down
58 changes: 37 additions & 21 deletions crates/turborepo-lib/src/run/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
};

use chrono::Local;
use tracing::debug;
use tracing::{debug, Instrument};
use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf};
use turborepo_analytics::{start_analytics, AnalyticsHandle, AnalyticsSender};
use turborepo_api_client::{APIAuth, APIClient};
Expand Down Expand Up @@ -253,7 +253,10 @@ impl RunBuilder {
.with_single_package_mode(self.opts.run_opts.single_package)
.with_allow_no_package_manager(self.opts.repo_opts.allow_no_package_manager);

let graph = builder.build().await;
let graph = builder
.build()
.instrument(tracing::info_span!("pkg_dep_graph_build"))
.await;

match graph {
Ok(graph) => graph,
Expand Down Expand Up @@ -285,19 +288,25 @@ impl RunBuilder {
}
};

let (scm, repo_index) = scm_task.await.expect("detecting scm panicked");
let (scm, repo_index) = {
let _span = tracing::info_span!("scm_task_await").entered();
scm_task.await.expect("detecting scm panicked")
};
Comment thread
anthonyshew marked this conversation as resolved.
Outdated
let repo_index = Arc::new(repo_index);
debug!(
"RunBuilder creating AsyncCache with cache_dir={}, repo_root={}",
self.opts.cache_opts.cache_dir, self.repo_root
);
let async_cache = AsyncCache::new(
&self.opts.cache_opts,
&self.repo_root,
self.api_client.clone(),
self.api_auth.clone(),
self.analytics_sender.take(),
)?;
let async_cache = {
let _span = tracing::info_span!("async_cache_new").entered();
AsyncCache::new(
&self.opts.cache_opts,
&self.repo_root,
self.api_client.clone(),
self.api_auth.clone(),
self.analytics_sender.take(),
)?
};

// restore config from task access trace if it's enabled
let task_access = TaskAccess::new(self.repo_root.clone(), async_cache.clone(), &scm);
Expand Down Expand Up @@ -348,18 +357,25 @@ impl RunBuilder {

pkg_dep_graph.validate()?;

let filtered_pkgs = Self::calculate_filtered_packages(
&self.repo_root,
&self.opts,
&pkg_dep_graph,
&scm,
&root_turbo_json,
)?;
let filtered_pkgs = {
let _span = tracing::info_span!("calculate_filtered_packages").entered();
Self::calculate_filtered_packages(
&self.repo_root,
&self.opts,
&pkg_dep_graph,
&scm,
&root_turbo_json,
)?
};

let env_at_execution_start = EnvironmentVariableMap::infer();
// Pre-warm the turbo.json cache: read and parse all package turbo.json
// files in parallel before the engine builder needs them sequentially.
turbo_json_loader.preload_all();
let env_at_execution_start = {
let _span = tracing::info_span!("env_infer").entered();
EnvironmentVariableMap::infer()
};
{
let _span = tracing::info_span!("turbo_json_preload").entered();
turbo_json_loader.preload_all();
}

let mut engine = self.build_engine(
&pkg_dep_graph,
Expand Down
3 changes: 3 additions & 0 deletions crates/turborepo-lib/src/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ impl Run {
let mut internal_deps_result = None;
let mut global_file_result = None;

let _hash_scope_span = tracing::info_span!("hash_scope").entered();
rayon::scope(|s| {
s.spawn(|_| {
let _span = tracing::info_span!("calculate_file_hashes_task").entered();
Expand Down Expand Up @@ -655,6 +656,8 @@ impl Run {
});
});

drop(_hash_scope_span);

let package_inputs_hashes = file_hash_result.expect("file hash task did not complete")?;
let root_internal_dependencies_hash =
internal_deps_result.expect("internal deps task did not complete")?;
Expand Down
2 changes: 2 additions & 0 deletions crates/turborepo-lib/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ pub fn run() -> Result<i32, Error> {
let _ = subscriber.enable_chrome_tracing(file_path, include_args);
}

let _span = tracing::info_span!("shim_run").entered();

// Create the runtime with all implementations
let runtime = ShimRuntime::new(
TurboCliRunner::new(&subscriber),
Expand Down
15 changes: 11 additions & 4 deletions crates/turborepo-shim/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,22 @@ where
// it to execute local turbo. We simply use it to set the `--single-package`
// and `--cwd` flags.
if is_turbo_binary_path_set() {
let repo_state = match RepoState::infer(&args.cwd) {
Ok(state) => state,
Err(e) => return ShimResult::ShimError(e.into()),
let repo_state = {
let _span = tracing::info_span!("repo_inference").entered();
match RepoState::infer(&args.cwd) {
Ok(state) => state,
Err(e) => return ShimResult::ShimError(e.into()),
}
};
debug!("Repository Root: {}", repo_state.root);
return run_cli(runtime, Some(repo_state), color_config);
}

match RepoState::infer(&args.cwd) {
let repo_result = {
let _span = tracing::info_span!("repo_inference").entered();
RepoState::infer(&args.cwd)
};
match repo_result {
Ok(repo_state) => {
debug!("Repository Root: {}", repo_state.root);
run_correct_turbo(runtime, repo_state, args, color_config)
Expand Down
Loading