Skip to content

Commit 00b9882

Browse files
committed
Auto merge of #13399 - epage:timing, r=weihanglo
feat(cli): Allow logging to chrome traces ### What does this PR try to resolve? > The time from executing cargo to executing rustc is 230 ms. I wonder if there’s scope for caching whatever expensive computations cargo is doing here. *Source: https://davidlattimore.github.io/working-on-rust-iteration-time.html* This made me curious where the time was going. I've been meaning to try out `tracing-chrome` for a while and this gave me the opportunity. This adds `CARGO_LOG_PROFILE=<bool>` and `CARGO_LOG_PROFILE_CAPTURE_ARGS=<bool>` for enabling and controlling these trace files. These are perma-unstable env variables. Traces can be viewed at https://ui.perfetto.dev or `chrome://tracing`. Example: no-op `cargo check` run on `cargo-nextest`: ![image](https://github.com/rust-lang/cargo/assets/60961/f21e9c2d-86f6-41b9-8887-562d4fedb4e8) TODO - [ ] Find a place to document this, see https://doc.crates.io/contrib/tests/profiling.html#internal-profiler ### How should we test and review this PR? I looked in `config/` and didn't see a env variable parser to reuse (`get_cv_with_env` is too specialized). ### Additional information In past projects, I've been able to use features like this to better understand code bases, bugs, etc. Hopefully this can evolve to help on-board people one day. Most of the implementation was inspired by https://github.com/arxanas/git-branchless/blob/2923924dfbff07faa61d50771b6604cb18e64bc8/git-branchless-invoke/src/lib.rs#L55 `tracing-chrome` hasn't received updates recently, but it is also fairly quiet on Issues and PRs, so this might just be "maturity". It does have over a million downloads. It also is only enabled if explicitly opted into. rustup added trace visualization in rust-lang/rustup#3287 using [open telemetry](https://crates.io/crates/tracing-opentelemetry) but it is behind a feature flag and and requires running a server to receive the traces.
2 parents 39e21a9 + 6d8708a commit 00b9882

File tree

17 files changed

+69
-151
lines changed

17 files changed

+69
-151
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ time = { version = "0.3", features = ["parsing", "formatting", "serde"] }
9999
toml = "0.8.10"
100100
toml_edit = { version = "0.22.6", features = ["serde"] }
101101
tracing = "0.1.40" # be compatible with rustc_log: https://github.com/rust-lang/rust/blob/e51e98dde6a/compiler/rustc_log/Cargo.toml#L9
102+
tracing-chrome = "0.7.1"
102103
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
103104
unicase = "2.7.0"
104105
unicode-width = "0.1.11"
@@ -198,6 +199,7 @@ time.workspace = true
198199
toml.workspace = true
199200
toml_edit.workspace = true
200201
tracing.workspace = true
202+
tracing-chrome.workspace = true
201203
tracing-subscriber.workspace = true
202204
unicase.workspace = true
203205
unicode-width.workspace = true

src/bin/cargo/main.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ mod commands;
1818
use crate::command_prelude::*;
1919

2020
fn main() {
21-
setup_logger();
21+
let _guard = setup_logger();
2222

2323
let mut gctx = match GlobalContext::default() {
2424
Ok(gctx) => gctx,
@@ -41,16 +41,43 @@ fn main() {
4141
}
4242
}
4343

44-
fn setup_logger() {
45-
let env = tracing_subscriber::EnvFilter::from_env("CARGO_LOG");
44+
fn setup_logger() -> Option<tracing_chrome::FlushGuard> {
45+
#![allow(clippy::disallowed_methods)]
46+
47+
use tracing_subscriber::prelude::*;
4648

47-
tracing_subscriber::fmt()
49+
let env = tracing_subscriber::EnvFilter::from_env("CARGO_LOG");
50+
let fmt_layer = tracing_subscriber::fmt::layer()
4851
.with_timer(tracing_subscriber::fmt::time::Uptime::default())
4952
.with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr()))
5053
.with_writer(std::io::stderr)
51-
.with_env_filter(env)
52-
.init();
54+
.with_filter(env);
55+
56+
let (profile_layer, profile_guard) =
57+
if env_to_bool(std::env::var_os("CARGO_LOG_PROFILE").as_deref()) {
58+
let capture_args =
59+
env_to_bool(std::env::var_os("CARGO_LOG_PROFILE_CAPTURE_ARGS").as_deref());
60+
let (layer, guard) = tracing_chrome::ChromeLayerBuilder::new()
61+
.include_args(capture_args)
62+
.build();
63+
(Some(layer), Some(guard))
64+
} else {
65+
(None, None)
66+
};
67+
68+
let registry = tracing_subscriber::registry()
69+
.with(fmt_layer)
70+
.with(profile_layer);
71+
registry.init();
5372
tracing::trace!(start = humantime::format_rfc3339(std::time::SystemTime::now()).to_string());
73+
profile_guard
74+
}
75+
76+
fn env_to_bool(os: Option<&OsStr>) -> bool {
77+
match os.and_then(|os| os.to_str()) {
78+
Some("1") | Some("true") => true,
79+
_ => false,
80+
}
5481
}
5582

5683
/// Table for defining the aliases which come builtin in `Cargo`.

src/cargo/core/compiler/build_runner/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::core::compiler::{self, artifact, Unit};
99
use crate::core::PackageId;
1010
use crate::util::cache_lock::CacheLockMode;
1111
use crate::util::errors::CargoResult;
12-
use crate::util::profile;
1312
use anyhow::{bail, Context as _};
1413
use filetime::FileTime;
1514
use itertools::Itertools;
@@ -353,8 +352,6 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
353352
/// place.
354353
#[tracing::instrument(skip_all)]
355354
pub fn prepare(&mut self) -> CargoResult<()> {
356-
let _p = profile::start("preparing layout");
357-
358355
self.files
359356
.as_mut()
360357
.unwrap()

src/cargo/core/compiler/custom_build.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ use crate::core::compiler::fingerprint::DirtyReason;
3838
use crate::core::compiler::job_queue::JobState;
3939
use crate::core::{profiles::ProfileRoot, PackageId, Target};
4040
use crate::util::errors::CargoResult;
41+
use crate::util::internal;
4142
use crate::util::machine_message::{self, Message};
42-
use crate::util::{internal, profile};
4343
use anyhow::{bail, Context as _};
4444
use cargo_platform::Cfg;
4545
use cargo_util::paths;
@@ -196,12 +196,6 @@ impl LinkArgTarget {
196196
/// Prepares a `Work` that executes the target as a custom build script.
197197
#[tracing::instrument(skip_all)]
198198
pub fn prepare(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<Job> {
199-
let _p = profile::start(format!(
200-
"build script prepare: {}/{}",
201-
unit.pkg,
202-
unit.target.name()
203-
));
204-
205199
let metadata = build_runner.get_run_build_script_metadata(unit);
206200
if build_runner
207201
.build_script_outputs

src/cargo/core/compiler/fingerprint/mod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ use crate::core::Package;
377377
use crate::util::errors::CargoResult;
378378
use crate::util::interning::InternedString;
379379
use crate::util::{self, try_canonicalize};
380-
use crate::util::{internal, path_args, profile, StableHasher};
380+
use crate::util::{internal, path_args, StableHasher};
381381
use crate::{GlobalContext, CARGO_ENV};
382382

383383
use super::custom_build::BuildDeps;
@@ -408,11 +408,6 @@ pub fn prepare_target(
408408
unit: &Unit,
409409
force: bool,
410410
) -> CargoResult<Job> {
411-
let _p = profile::start(format!(
412-
"fingerprint: {} / {}",
413-
unit.pkg.package_id(),
414-
unit.target.name()
415-
));
416411
let bcx = build_runner.bcx;
417412
let loc = build_runner.files().fingerprint_file_path(unit, "");
418413

src/cargo/core/compiler/job_queue/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ use crate::util::diagnostic_server::{self, DiagnosticPrinter};
144144
use crate::util::errors::AlreadyPrintedError;
145145
use crate::util::machine_message::{self, Message as _};
146146
use crate::util::CargoResult;
147-
use crate::util::{self, internal, profile};
147+
use crate::util::{self, internal};
148148
use crate::util::{DependencyQueue, GlobalContext, Progress, ProgressStyle, Queue};
149149

150150
/// This structure is backed by the `DependencyQueue` type and manages the
@@ -473,7 +473,6 @@ impl<'gctx> JobQueue<'gctx> {
473473
build_runner: &mut BuildRunner<'_, '_>,
474474
plan: &mut BuildPlan,
475475
) -> CargoResult<()> {
476-
let _p = profile::start("executing the job graph");
477476
self.queue.queue_finished();
478477

479478
let progress =

src/cargo/core/compiler/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ use crate::core::{Feature, PackageId, Target, Verbosity};
9393
use crate::util::errors::{CargoResult, VerboseError};
9494
use crate::util::interning::InternedString;
9595
use crate::util::machine_message::{self, Message};
96-
use crate::util::{add_path_args, internal, profile};
96+
use crate::util::{add_path_args, internal};
9797
use cargo_util::{paths, ProcessBuilder, ProcessError};
9898
use cargo_util_schemas::manifest::TomlDebugInfo;
9999
use cargo_util_schemas::manifest::TomlTrimPaths;
@@ -175,7 +175,6 @@ fn compile<'gctx>(
175175

176176
// Build up the work to be done to compile this unit, enqueuing it once
177177
// we've got everything constructed.
178-
let p = profile::start(format!("preparing: {}/{}", unit.pkg, unit.target.name()));
179178
fingerprint::prepare_init(build_runner, unit)?;
180179

181180
let job = if unit.mode.is_run_custom_build() {
@@ -216,7 +215,6 @@ fn compile<'gctx>(
216215
job
217216
};
218217
jobs.enqueue(build_runner, unit, job)?;
219-
drop(p);
220218

221219
// Be sure to compile all dependencies of this target as well.
222220
let deps = Vec::from(build_runner.unit_deps(unit)); // Create vec due to mutable borrow.

src/cargo/core/global_cache_tracker.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,6 @@ impl GlobalCacheTracker {
552552
clean_ctx: &mut CleanContext<'_>,
553553
gc_opts: &GcOpts,
554554
) -> CargoResult<()> {
555-
let _p = crate::util::profile::start("cleaning global cache files");
556555
let gctx = clean_ctx.gctx;
557556
let base = BasePaths {
558557
index: gctx.registry_index_path().into_path_unlocked(),
@@ -706,7 +705,6 @@ impl GlobalCacheTracker {
706705
sync_size: bool,
707706
delete_paths: &mut Vec<PathBuf>,
708707
) -> CargoResult<()> {
709-
let _p = crate::util::profile::start("global cache db sync");
710708
debug!(target: "gc", "starting db sync");
711709
// For registry_index and git_db, add anything that is missing in the db.
712710
Self::update_parent_for_missing_from_db(conn, now, REGISTRY_INDEX_TABLE, &base.index)?;
@@ -804,9 +802,6 @@ impl GlobalCacheTracker {
804802
parent_table_name: &str,
805803
base_path: &Path,
806804
) -> CargoResult<()> {
807-
let _p = crate::util::profile::start(format!(
808-
"update parent db for missing from db {parent_table_name}"
809-
));
810805
trace!(target: "gc", "checking for untracked parent to add to {parent_table_name}");
811806
let names = Self::names_from(base_path)?;
812807

@@ -833,7 +828,6 @@ impl GlobalCacheTracker {
833828
table_name: &str,
834829
base_path: &Path,
835830
) -> CargoResult<()> {
836-
let _p = crate::util::profile::start(format!("update db for removed {table_name}"));
837831
trace!(target: "gc", "checking for db entries to remove from {table_name}");
838832
let mut select_stmt = conn.prepare_cached(&format!(
839833
"SELECT {table_name}.rowid, {parent_table_name}.name, {table_name}.name
@@ -863,9 +857,6 @@ impl GlobalCacheTracker {
863857
child_base_paths: &[&Path],
864858
delete_paths: &mut Vec<PathBuf>,
865859
) -> CargoResult<()> {
866-
let _p = crate::util::profile::start(format!(
867-
"update db parent for removed from disk {parent_table_name}"
868-
));
869860
trace!(target: "gc", "checking for db entries to remove from {parent_table_name}");
870861
let mut select_stmt =
871862
conn.prepare_cached(&format!("SELECT rowid, name FROM {parent_table_name}"))?;
@@ -899,7 +890,6 @@ impl GlobalCacheTracker {
899890
now: Timestamp,
900891
base_path: &Path,
901892
) -> CargoResult<()> {
902-
let _p = crate::util::profile::start("populate untracked crate");
903893
trace!(target: "gc", "populating untracked crate files");
904894
let mut insert_stmt = conn.prepare_cached(
905895
"INSERT INTO registry_crate (registry_id, name, size, timestamp)
@@ -939,7 +929,6 @@ impl GlobalCacheTracker {
939929
base_path: &Path,
940930
populate_size: bool,
941931
) -> CargoResult<()> {
942-
let _p = crate::util::profile::start(format!("populate untracked {table_name}"));
943932
trace!(target: "gc", "populating untracked files for {table_name}");
944933
// Gather names (and make sure they are in the database).
945934
let id_names = Self::names_from(&base_path)?;
@@ -1003,7 +992,6 @@ impl GlobalCacheTracker {
1003992
table_name: &str,
1004993
base_path: &Path,
1005994
) -> CargoResult<()> {
1006-
let _p = crate::util::profile::start(format!("update NULL sizes {table_name}"));
1007995
trace!(target: "gc", "updating NULL size information in {table_name}");
1008996
let mut null_stmt = conn.prepare_cached(&format!(
1009997
"SELECT {table_name}.rowid, {table_name}.name, {parent_table_name}.name
@@ -1570,7 +1558,6 @@ impl DeferredGlobalLastUse {
15701558
/// This will also clear the state of `self`.
15711559
#[tracing::instrument(skip_all)]
15721560
pub fn save(&mut self, tracker: &mut GlobalCacheTracker) -> CargoResult<()> {
1573-
let _p = crate::util::profile::start("saving last-use data");
15741561
trace!(target: "gc", "saving last-use data");
15751562
if self.is_empty() {
15761563
return Ok(());

src/cargo/core/resolver/features.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,6 @@ impl<'a, 'gctx> FeatureResolver<'a, 'gctx> {
455455
requested_targets: &[CompileKind],
456456
opts: FeatureOpts,
457457
) -> CargoResult<ResolvedFeatures> {
458-
use crate::util::profile;
459-
let _p = profile::start("resolve features");
460458
let track_for_host = opts.decouple_host_deps || opts.ignore_inactive_targets;
461459
let mut r = FeatureResolver {
462460
ws,

src/cargo/core/resolver/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ use crate::core::{Dependency, PackageId, Registry, Summary};
7070
use crate::util::context::GlobalContext;
7171
use crate::util::errors::CargoResult;
7272
use crate::util::network::PollExt;
73-
use crate::util::profile;
7473

7574
use self::context::ResolverContext;
7675
use self::dep_cache::RegistryQueryer;
@@ -131,7 +130,6 @@ pub fn resolve(
131130
resolve_version: ResolveVersion,
132131
gctx: Option<&GlobalContext>,
133132
) -> CargoResult<Resolve> {
134-
let _p = profile::start("resolving");
135133
let first_version = match gctx {
136134
Some(config) if config.cli_unstable().direct_minimal_versions => {
137135
Some(VersionOrdering::MinimumVersionsFirst)

src/cargo/ops/cargo_compile/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use crate::ops;
5454
use crate::ops::resolve::WorkspaceResolve;
5555
use crate::util::context::GlobalContext;
5656
use crate::util::interning::InternedString;
57-
use crate::util::{profile, CargoResult, StableHasher};
57+
use crate::util::{CargoResult, StableHasher};
5858

5959
mod compile_filter;
6060
pub use compile_filter::{CompileFilter, FilterRule, LibRule};
@@ -155,7 +155,6 @@ pub fn compile_ws<'a>(
155155
return Compilation::new(&bcx);
156156
}
157157
crate::core::gc::auto_gc(bcx.gctx);
158-
let _p = profile::start("compiling");
159158
let build_runner = BuildRunner::new(&bcx)?;
160159
build_runner.compile(exec)
161160
}

src/cargo/ops/resolve.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ use crate::ops;
7171
use crate::sources::PathSource;
7272
use crate::util::cache_lock::CacheLockMode;
7373
use crate::util::errors::CargoResult;
74-
use crate::util::{profile, CanonicalUrl};
74+
use crate::util::CanonicalUrl;
7575
use anyhow::Context as _;
7676
use std::collections::{HashMap, HashSet};
7777
use tracing::{debug, trace};
@@ -147,8 +147,6 @@ pub fn resolve_ws_with_opts<'gctx>(
147147
// Second, resolve with precisely what we're doing. Filter out
148148
// transitive dependencies if necessary, specify features, handle
149149
// overrides, etc.
150-
let _p = profile::start("resolving with overrides...");
151-
152150
add_overrides(&mut registry, ws)?;
153151

154152
for (replace_spec, dep) in ws.root_replace() {

src/cargo/util/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ pub mod job;
5454
mod lockserver;
5555
pub mod machine_message;
5656
pub mod network;
57-
pub mod profile;
5857
mod progress;
5958
mod queue;
6059
pub mod restricted_names;

0 commit comments

Comments
 (0)