perf: Add more tracing spans into startup path#11965
Merged
anthonyshew merged 15 commits intomainfrom Feb 23, 2026
Merged
Conversation
…very Three targeted optimizations to the turbo run hot path: 1. Engine builder: Cache turbo.json chain per package and move the visited check before the expensive task_definition() call. The chain only depends on the package name, so multiple tasks in the same package reuse the cached result. 2. Task visitor: Defer env() computation to non-dry-run branches. The execution environment is unused during dry runs, avoiding per-task RwLock acquisition and env var map cloning. 3. find_untracked_files: Replace Mutex<Vec> with per-thread local buffers flushed via mpsc channel on drop, eliminating per-file mutex contention in the parallel walker.
Parallelize several sequential phases of turbo run's pre-execution pipeline: dependency resolution, turbo.json loading, and task summary construction. Also reduce per-call allocation overhead in the task hash tracker and gix index classification.
…parallelize-hot-path # Conflicts: # crates/turborepo-scm/src/repo_index.rs
…parallelize-hot-path
Adds profiling visibility to functions that were invisible in --profile output: TLS initialization, rayon-spawned hash tasks, Visitor constructor, Engine scheduler, and per-task cache phases.
…/add-profiling-spans
…/add-profiling-spans
Store task hashes as Arc<str> in TaskHashTrackerState instead of String. In calculate_dependency_hashes, cloning an Arc<str> is a ref count bump instead of a heap allocation. For the api monorepo (1687 tasks, ~3 deps each), this eliminates ~5000 String heap allocations per run.
…Summary Removes the .to_string() conversion in the HashTrackerInfo::hash() trait impl by changing the trait return type from Option<String> to Option<Arc<str>>. Also changes SharedTaskSummary.hash to Arc<str> so the Arc flows all the way to serialization without any String allocation.
The Arc<str> fields in TaskHashTrackerState and SharedTaskSummary require serde's "rc" feature for Serialize. Previously this worked via transitive feature activation; make it explicit so it doesn't break if the transitive path changes.
…arc-str-dependency-hashes
The --profile output previously had no visibility into the pre-execution phases of turbo run. This made it impossible to diagnose where startup overhead was coming from. Add info-level tracing spans to every significant phase: - shim_run: top-level shim execution - cli_run: CLI dispatch (arg parsing, http client, telemetry) - http_client_init: TLS initialization for reqwest - telemetry_init: telemetry client setup - command_base_new: config loading and opts construction - run_builder_new: API client and auth setup - pkg_dep_graph_build: package graph construction - scm_task_await: waiting for background SCM/git index - async_cache_new: cache initialization - calculate_filtered_packages: package filtering - env_infer: environment variable snapshot - turbo_json_preload: turbo.json cache warming - build_engine: task graph construction - hash_scope: parallel file hashing - start_ui: UI initialization - repo_inference: repository root detection These spans appear in both the chrome trace JSON and the generated markdown summary when using --profile.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Holding an EnteredSpan guard across .await corrupts tracing's thread-local state when the future resumes on a different tokio worker thread. Use .instrument() which correctly re-enters the span on whichever thread the future polls on.
Contributor
Coverage Report
|
github-actions Bot
added a commit
that referenced
this pull request
Feb 23, 2026
## Release v2.8.11-canary.23 Versioned docs: https://v2-8-11-canary-23.turborepo.dev ### Changes - release(turborepo): 2.8.11-canary.22 (#11963) (`ac0f273`) - chore: Migrate to Ultracite (#11948) (`a0db6bf`) - perf: Add more tracing spans into startup path (#11965) (`23e144d`) --------- Co-authored-by: Turbobot <turbobot@vercel.com>
github-actions Bot
added a commit
that referenced
this pull request
Feb 23, 2026
## Release v2.8.11-canary.24 Versioned docs: https://v2-8-11-canary-24.turborepo.dev ### Changes - perf: Add more tracing spans into startup path (#11965) (`23e144d`) - release(turborepo): 2.8.11-canary.23 (#11966) (`b425c39`) - perf: Defer TLS initialization to a background thread (#11967) (`f1d487f`) --------- Co-authored-by: Turbobot <turbobot@vercel.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--profilepreviously had no visibility into pre-execution phases, making it impossible to diagnose startup overheadinfo-level tracing spans to every significant phase between process start and task executionWhat this revealed
On this repo with
turbo run check-types --skip-infer --profile:visit(task execution)build_http_client(TLS init)new_from_gix_index(git index)compile_globsfind_untracked_filesfetch(cache I/O)TLS initialization alone accounts for 10% of the non-execution overhead — even when remote caching is disabled. This data wasn't visible before.
Testing
Verified
--profile=profile.jsonproduces spans for all new instrumentation points. The.json.mdsummary correctly reports self-time and call trees for the new spans.