Skip to content

Commit 02f07d4

Browse files
authored
perf: parallelize remappings provider (#11536)
* perf: parallelize remappings provider * patch * Revert "patch" This reverts commit a3521ec.
1 parent b104ef4 commit 02f07d4

File tree

4 files changed

+66
-47
lines changed

4 files changed

+66
-47
lines changed

Cargo.lock

Lines changed: 1 addition & 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
@@ -153,9 +153,11 @@ scrypt.opt-level = 3
153153

154154
# Misc.
155155
rayon.opt-level = 3
156+
rayon-core.opt-level = 3
156157
regex.opt-level = 3
157158
regex-syntax.opt-level = 3
158159
regex-automata.opt-level = 3
160+
walkdir.opt-level = 3
159161

160162
# Override packages which aren't perf-sensitive for faster compilation speed and smaller binary size.
161163
[profile.release.package]

crates/config/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ heck.workspace = true
3434
itertools.workspace = true
3535
mesc.workspace = true
3636
number_prefix = "0.4"
37+
rayon.workspace = true
3738
regex.workspace = true
3839
reqwest.workspace = true
3940
semver = { workspace = true, features = ["serde"] }

crates/config/src/providers/remappings.rs

Lines changed: 62 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use figment::{
44
value::{Dict, Map},
55
};
66
use foundry_compilers::artifacts::remappings::{RelativeRemapping, Remapping};
7+
use rayon::prelude::*;
78
use std::{
89
borrow::Cow,
910
collections::{BTreeMap, HashSet, btree_map::Entry},
@@ -207,19 +208,16 @@ impl RemappingsProvider<'_> {
207208
// TODO: if a lib specifies contexts for remappings manually, we need to figure out how to
208209
// resolve that
209210
if self.auto_detect_remappings {
211+
let (nested_foundry_remappings, auto_detected_remappings) = rayon::join(
212+
|| self.find_nested_foundry_remappings(),
213+
|| self.auto_detect_remappings(),
214+
);
215+
210216
let mut lib_remappings = BTreeMap::new();
211-
// find all remappings of from libs that use a foundry.toml
212-
for r in self.lib_foundry_toml_remappings() {
217+
for r in nested_foundry_remappings {
213218
insert_closest(&mut lib_remappings, r.context, r.name, r.path.into());
214219
}
215-
// use auto detection for all libs
216-
for r in self
217-
.lib_paths
218-
.iter()
219-
.map(|lib| self.root.join(lib))
220-
.inspect(|lib| trace!(?lib, "find all remappings"))
221-
.flat_map(|lib| Remapping::find_many(&lib))
222-
{
220+
for r in auto_detected_remappings {
223221
// this is an additional safety check for weird auto-detected remappings
224222
if ["lib/", "src/", "contracts/"].contains(&r.name.as_str()) {
225223
trace!(target: "forge", "- skipping the remapping");
@@ -246,50 +244,67 @@ impl RemappingsProvider<'_> {
246244
}
247245

248246
/// Returns all remappings declared in foundry.toml files of libraries
249-
fn lib_foundry_toml_remappings(&self) -> impl Iterator<Item = Remapping> + '_ {
247+
fn find_nested_foundry_remappings(&self) -> impl Iterator<Item = Remapping> + '_ {
250248
self.lib_paths
251-
.iter()
249+
.par_iter()
252250
.map(|p| if p.is_absolute() { self.root.join("lib") } else { self.root.join(p) })
253251
.flat_map(foundry_toml_dirs)
254-
.inspect(|lib| {
255-
trace!("find all remappings of nested foundry.toml lib: {:?}", lib);
252+
.flat_map_iter(|lib| {
253+
trace!(?lib, "find all remappings of nested foundry.toml");
254+
self.nested_foundry_remappings(&lib)
256255
})
257-
.flat_map(|lib: PathBuf| {
258-
// load config, of the nested lib if it exists
259-
let Ok(config) = Config::load_with_root(&lib) else { return vec![] };
260-
let config = config.sanitized();
261-
262-
// if the configured _src_ directory is set to something that
263-
// [Remapping::find_many()] doesn't classify as a src directory (src, contracts,
264-
// lib), then we need to manually add a remapping here
265-
let mut src_remapping = None;
266-
if ![Path::new("src"), Path::new("contracts"), Path::new("lib")]
267-
.contains(&config.src.as_path())
268-
&& let Some(name) = lib.file_name().and_then(|s| s.to_str())
269-
{
270-
let mut r = Remapping {
271-
context: None,
272-
name: format!("{name}/"),
273-
path: format!("{}", lib.join(&config.src).display()),
274-
};
275-
if !r.path.ends_with('/') {
276-
r.path.push('/')
277-
}
278-
src_remapping = Some(r);
279-
}
256+
.collect::<Vec<_>>()
257+
.into_iter()
258+
}
280259

281-
// Eventually, we could set context for remappings at this location,
282-
// taking into account the OS platform. We'll need to be able to handle nested
283-
// contexts depending on dependencies for this to work.
284-
// For now, we just leave the default context (none).
285-
let mut remappings =
286-
config.remappings.into_iter().map(Remapping::from).collect::<Vec<Remapping>>();
260+
fn nested_foundry_remappings(&self, lib: &Path) -> Vec<Remapping> {
261+
// load config, of the nested lib if it exists
262+
let Ok(config) = Config::load_with_root(lib) else { return vec![] };
263+
let config = config.sanitized();
264+
265+
// if the configured _src_ directory is set to something that
266+
// `Remapping::find_many` doesn't classify as a src directory (src, contracts,
267+
// lib), then we need to manually add a remapping here
268+
let mut src_remapping = None;
269+
if ![Path::new("src"), Path::new("contracts"), Path::new("lib")]
270+
.contains(&config.src.as_path())
271+
&& let Some(name) = lib.file_name().and_then(|s| s.to_str())
272+
{
273+
let mut r = Remapping {
274+
context: None,
275+
name: format!("{name}/"),
276+
path: format!("{}", lib.join(&config.src).display()),
277+
};
278+
if !r.path.ends_with('/') {
279+
r.path.push('/')
280+
}
281+
src_remapping = Some(r);
282+
}
287283

288-
if let Some(r) = src_remapping {
289-
remappings.push(r);
290-
}
291-
remappings
284+
// Eventually, we could set context for remappings at this location,
285+
// taking into account the OS platform. We'll need to be able to handle nested
286+
// contexts depending on dependencies for this to work.
287+
// For now, we just leave the default context (none).
288+
let mut remappings =
289+
config.remappings.into_iter().map(Remapping::from).collect::<Vec<Remapping>>();
290+
291+
if let Some(r) = src_remapping {
292+
remappings.push(r);
293+
}
294+
remappings
295+
}
296+
297+
/// Auto detect remappings from the lib paths
298+
fn auto_detect_remappings(&self) -> impl Iterator<Item = Remapping> + '_ {
299+
self.lib_paths
300+
.par_iter()
301+
.flat_map_iter(|lib| {
302+
let lib = self.root.join(lib);
303+
trace!(?lib, "find all remappings");
304+
Remapping::find_many(&lib)
292305
})
306+
.collect::<Vec<_>>()
307+
.into_iter()
293308
}
294309
}
295310

0 commit comments

Comments
 (0)