Skip to content

Commit b75281b

Browse files
committed
Auto merge of #10568 - Muscraft:rfc2906-part8, r=epage
Part 8 of RFC2906 - Keep `InheritableFields` in a `LazyCell` inside `… Tracking issue: #8415 RFC: rust-lang/rfcs#2906 Part 1: #10497 Part 2: #10517 Part 3: #10538 Part 4: #10548 Part 5: #10563 Part 6: #10564 Part 7: #10565 This PR focuses on optimizations surrounding `InheritabeFields` and searching for a `WorkspaceRootConfig`: - Keep `InheritableFields` in a `LazyCell` inside `to_real_manifest` so we only search for a workspace root once per `to_real_manifest` - Changed calls for getting a workspace root to use `inherit_cell.try_borrow_with()` [Testing Framework](https://gist.github.com/Muscraft/14f6879af27500e34584296edb468d15) Test Results: nest=1, runs=7, members=75, step=25 - 25 Members: - Optimized: 0.145s - Not Optimized: 0.181s - Normal: 0.141s - Percent change from Normal: 2.837% - 50 Members - Optimized: 0.152s - Not Optimized: 0.267s - Normal: 0.141s - Percent change from Normal: 7.801% nest=2, runs=7, members=75, step=25 - 25 Members - Optimized: 0.147s, - Not Optimized: 0.437s - Normal: 0.14s - Percent change from Normal: 5.0% - 50 Members - Optimized: 0.159s - Not Optimized: 1.023s - Normal: 0.141s - Percent change from Normal: 12.766% Using a `LazyCell` for `InheritableFields` brought down runtimes to more acceptable levels. It is worth noting that this is a very harsh test case and not one that represents real-world scenarios. That being said there are still some optimizations that could be done if we need to. The biggest one is making sure we only parse a `Cargo.toml` once. Remaining implementation work for the RFC - `cargo-add` support, see [epage's comment](#8415 (comment)) - More optimizations, as needed
2 parents ec83f8d + 125c274 commit b75281b

File tree

1 file changed

+43
-89
lines changed

1 file changed

+43
-89
lines changed

src/cargo/util/toml/mod.rs

+43-89
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::str;
88
use anyhow::{anyhow, bail, Context as _};
99
use cargo_platform::Platform;
1010
use cargo_util::paths;
11+
use lazycell::LazyCell;
1112
use log::{debug, trace};
1213
use semver::{self, VersionReq};
1314
use serde::de;
@@ -1496,8 +1497,8 @@ impl TomlManifest {
14961497
) -> CargoResult<(Manifest, Vec<PathBuf>)> {
14971498
fn get_ws(
14981499
config: &Config,
1499-
resolved_path: PathBuf,
1500-
workspace_config: WorkspaceConfig,
1500+
resolved_path: &Path,
1501+
workspace_config: &WorkspaceConfig,
15011502
) -> CargoResult<InheritableFields> {
15021503
match workspace_config {
15031504
WorkspaceConfig::Root(root) => Ok(root.inheritable().clone()),
@@ -1565,19 +1566,22 @@ impl TomlManifest {
15651566

15661567
let resolved_path = package_root.join("Cargo.toml");
15671568

1568-
let version = project.version.clone().resolve(&features, "version", || {
1569-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.version()
1570-
})?;
1569+
let inherit_cell: LazyCell<InheritableFields> = LazyCell::new();
1570+
let inherit =
1571+
|| inherit_cell.try_borrow_with(|| get_ws(config, &resolved_path, &workspace_config));
1572+
1573+
let version = project
1574+
.version
1575+
.clone()
1576+
.resolve(&features, "version", || inherit()?.version())?;
15711577

15721578
project.version = MaybeWorkspace::Defined(version.clone());
15731579

15741580
let pkgid = project.to_package_id(source_id, version)?;
15751581

15761582
let edition = if let Some(edition) = project.edition.clone() {
15771583
let edition: Edition = edition
1578-
.resolve(&features, "edition", || {
1579-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.edition()
1580-
})?
1584+
.resolve(&features, "edition", || inherit()?.edition())?
15811585
.parse()
15821586
.with_context(|| "failed to parse the `edition` key")?;
15831587
project.edition = Some(MaybeWorkspace::Defined(edition.to_string()));
@@ -1602,9 +1606,7 @@ impl TomlManifest {
16021606
let rust_version = if let Some(rust_version) = &project.rust_version {
16031607
let rust_version = rust_version
16041608
.clone()
1605-
.resolve(&features, "rust_version", || {
1606-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.rust_version()
1607-
})?;
1609+
.resolve(&features, "rust_version", || inherit()?.rust_version())?;
16081610
let req = match semver::VersionReq::parse(&rust_version) {
16091611
// Exclude semver operators like `^` and pre-release identifiers
16101612
Ok(req) if rust_version.chars().all(|c| c.is_ascii_digit() || c == '.') => req,
@@ -1700,20 +1702,22 @@ impl TomlManifest {
17001702
new_deps: Option<&BTreeMap<String, TomlDependency>>,
17011703
kind: Option<DepKind>,
17021704
workspace_config: &WorkspaceConfig,
1705+
inherit_cell: &LazyCell<InheritableFields>,
17031706
) -> CargoResult<Option<BTreeMap<String, TomlDependency>>> {
17041707
let dependencies = match new_deps {
17051708
Some(dependencies) => dependencies,
17061709
None => return Ok(None),
17071710
};
1711+
1712+
let inherit = || {
1713+
inherit_cell.try_borrow_with(|| {
1714+
get_ws(cx.config, &cx.root.join("Cargo.toml"), &workspace_config)
1715+
})
1716+
};
1717+
17081718
let mut deps: BTreeMap<String, TomlDependency> = BTreeMap::new();
17091719
for (n, v) in dependencies.iter() {
1710-
let resolved = v.clone().resolve(features, n, cx, || {
1711-
get_ws(
1712-
cx.config,
1713-
cx.root.join("Cargo.toml"),
1714-
workspace_config.clone(),
1715-
)
1716-
})?;
1720+
let resolved = v.clone().resolve(features, n, cx, || inherit())?;
17171721
let dep = resolved.to_dependency(n, cx, kind)?;
17181722
validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?;
17191723
cx.deps.push(dep);
@@ -1729,6 +1733,7 @@ impl TomlManifest {
17291733
me.dependencies.as_ref(),
17301734
None,
17311735
&workspace_config,
1736+
&inherit_cell,
17321737
)?;
17331738
if me.dev_dependencies.is_some() && me.dev_dependencies2.is_some() {
17341739
warn_on_deprecated("dev-dependencies", package_name, "package", cx.warnings);
@@ -1743,6 +1748,7 @@ impl TomlManifest {
17431748
dev_deps,
17441749
Some(DepKind::Development),
17451750
&workspace_config,
1751+
&inherit_cell,
17461752
)?;
17471753
if me.build_dependencies.is_some() && me.build_dependencies2.is_some() {
17481754
warn_on_deprecated("build-dependencies", package_name, "package", cx.warnings);
@@ -1757,6 +1763,7 @@ impl TomlManifest {
17571763
build_deps,
17581764
Some(DepKind::Build),
17591765
&workspace_config,
1766+
&inherit_cell,
17601767
)?;
17611768

17621769
let mut target: BTreeMap<String, TomlPlatform> = BTreeMap::new();
@@ -1772,6 +1779,7 @@ impl TomlManifest {
17721779
platform.dependencies.as_ref(),
17731780
None,
17741781
&workspace_config,
1782+
&inherit_cell,
17751783
)
17761784
.unwrap();
17771785
if platform.build_dependencies.is_some() && platform.build_dependencies2.is_some() {
@@ -1787,6 +1795,7 @@ impl TomlManifest {
17871795
build_deps,
17881796
Some(DepKind::Build),
17891797
&workspace_config,
1798+
&inherit_cell,
17901799
)
17911800
.unwrap();
17921801
if platform.dev_dependencies.is_some() && platform.dev_dependencies2.is_some() {
@@ -1802,6 +1811,7 @@ impl TomlManifest {
18021811
dev_deps,
18031812
Some(DepKind::Development),
18041813
&workspace_config,
1814+
&inherit_cell,
18051815
)
18061816
.unwrap();
18071817
target.insert(
@@ -1843,21 +1853,13 @@ impl TomlManifest {
18431853
let exclude = project
18441854
.exclude
18451855
.clone()
1846-
.map(|mw| {
1847-
mw.resolve(&features, "exclude", || {
1848-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.exclude()
1849-
})
1850-
})
1856+
.map(|mw| mw.resolve(&features, "exclude", || inherit()?.exclude()))
18511857
.transpose()?
18521858
.unwrap_or_default();
18531859
let include = project
18541860
.include
18551861
.clone()
1856-
.map(|mw| {
1857-
mw.resolve(&features, "include", || {
1858-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.include()
1859-
})
1860-
})
1862+
.map(|mw| mw.resolve(&features, "include", || inherit()?.include()))
18611863
.transpose()?
18621864
.unwrap_or_default();
18631865
let empty_features = BTreeMap::new();
@@ -1874,113 +1876,67 @@ impl TomlManifest {
18741876
description: project
18751877
.description
18761878
.clone()
1877-
.map(|mw| {
1878-
mw.resolve(&features, "description", || {
1879-
get_ws(config, resolved_path.clone(), workspace_config.clone())?
1880-
.description()
1881-
})
1882-
})
1879+
.map(|mw| mw.resolve(&features, "description", || inherit()?.description()))
18831880
.transpose()?,
18841881
homepage: project
18851882
.homepage
18861883
.clone()
1887-
.map(|mw| {
1888-
mw.resolve(&features, "homepage", || {
1889-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.homepage()
1890-
})
1891-
})
1884+
.map(|mw| mw.resolve(&features, "homepage", || inherit()?.homepage()))
18921885
.transpose()?,
18931886
documentation: project
18941887
.documentation
18951888
.clone()
1896-
.map(|mw| {
1897-
mw.resolve(&features, "documentation", || {
1898-
get_ws(config, resolved_path.clone(), workspace_config.clone())?
1899-
.documentation()
1900-
})
1901-
})
1889+
.map(|mw| mw.resolve(&features, "documentation", || inherit()?.documentation()))
19021890
.transpose()?,
19031891
readme: readme_for_project(
19041892
package_root,
19051893
project
19061894
.readme
19071895
.clone()
1908-
.map(|mw| {
1909-
mw.resolve(&features, "readme", || {
1910-
get_ws(config, resolved_path.clone(), workspace_config.clone())?
1911-
.readme(package_root)
1912-
})
1913-
})
1896+
.map(|mw| mw.resolve(&features, "readme", || inherit()?.readme(package_root)))
19141897
.transpose()?,
19151898
),
19161899
authors: project
19171900
.authors
19181901
.clone()
1919-
.map(|mw| {
1920-
mw.resolve(&features, "authors", || {
1921-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.authors()
1922-
})
1923-
})
1902+
.map(|mw| mw.resolve(&features, "authors", || inherit()?.authors()))
19241903
.transpose()?
19251904
.unwrap_or_default(),
19261905
license: project
19271906
.license
19281907
.clone()
1929-
.map(|mw| {
1930-
mw.resolve(&features, "license", || {
1931-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.license()
1932-
})
1933-
})
1908+
.map(|mw| mw.resolve(&features, "license", || inherit()?.license()))
19341909
.transpose()?,
19351910
license_file: project
19361911
.license_file
19371912
.clone()
19381913
.map(|mw| {
19391914
mw.resolve(&features, "license", || {
1940-
get_ws(config, resolved_path.clone(), workspace_config.clone())?
1941-
.license_file(package_root)
1915+
inherit()?.license_file(package_root)
19421916
})
19431917
})
19441918
.transpose()?,
19451919
repository: project
19461920
.repository
19471921
.clone()
1948-
.map(|mw| {
1949-
mw.resolve(&features, "repository", || {
1950-
get_ws(config, resolved_path.clone(), workspace_config.clone())?
1951-
.repository()
1952-
})
1953-
})
1922+
.map(|mw| mw.resolve(&features, "repository", || inherit()?.repository()))
19541923
.transpose()?,
19551924
keywords: project
19561925
.keywords
19571926
.clone()
1958-
.map(|mw| {
1959-
mw.resolve(&features, "keywords", || {
1960-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.keywords()
1961-
})
1962-
})
1927+
.map(|mw| mw.resolve(&features, "keywords", || inherit()?.keywords()))
19631928
.transpose()?
19641929
.unwrap_or_default(),
19651930
categories: project
19661931
.categories
19671932
.clone()
1968-
.map(|mw| {
1969-
mw.resolve(&features, "categories", || {
1970-
get_ws(config, resolved_path.clone(), workspace_config.clone())?
1971-
.categories()
1972-
})
1973-
})
1933+
.map(|mw| mw.resolve(&features, "categories", || inherit()?.categories()))
19741934
.transpose()?
19751935
.unwrap_or_default(),
19761936
badges: me
19771937
.badges
19781938
.clone()
1979-
.map(|mw| {
1980-
mw.resolve(&features, "badges", || {
1981-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.badges()
1982-
})
1983-
})
1939+
.map(|mw| mw.resolve(&features, "badges", || inherit()?.badges()))
19841940
.transpose()?
19851941
.unwrap_or_default(),
19861942
links: project.links.clone(),
@@ -2042,9 +1998,7 @@ impl TomlManifest {
20421998

20431999
let publish = project.publish.clone().map(|publish| {
20442000
publish
2045-
.resolve(&features, "publish", || {
2046-
get_ws(config, resolved_path.clone(), workspace_config.clone())?.publish()
2047-
})
2001+
.resolve(&features, "publish", || inherit()?.publish())
20482002
.unwrap()
20492003
});
20502004

@@ -2490,7 +2444,7 @@ impl TomlDependency {
24902444
cargo_features: &Features,
24912445
label: &str,
24922446
cx: &mut Context<'_, '_>,
2493-
get_inheritable: impl FnOnce() -> CargoResult<InheritableFields>,
2447+
get_inheritable: impl FnOnce() -> CargoResult<&'a InheritableFields>,
24942448
) -> CargoResult<TomlDependency> {
24952449
match self {
24962450
TomlDependency::Detailed(d) => Ok(TomlDependency::Detailed(d)),

0 commit comments

Comments
 (0)