Skip to content

Commit 49c5046

Browse files
Copilotkarthiknadig
andcommitted
Use Arc<[PathBuf]> to reduce cloning overhead for shared path lists
- Convert environment_directories and global_env_search_paths to Arc<[PathBuf]> for O(1) cloning in thread spawns instead of O(n) Vec cloning - Update find_python_environments and find_python_environments_in_paths_with_locators to accept &[PathBuf] slices instead of owned Vec<PathBuf> - Properly clone Arc references before move closures to maintain thread safety Co-authored-by: karthiknadig <3840081+karthiknadig@users.noreply.github.com>
1 parent 8c771e5 commit 49c5046

1 file changed

Lines changed: 23 additions & 17 deletions

File tree

crates/pet/src/find.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub fn find_and_report_envs(
125125
global_env_search_paths
126126
);
127127
find_python_environments(
128-
global_env_search_paths.clone(),
128+
&global_env_search_paths,
129129
reporter,
130130
locators,
131131
false,
@@ -139,14 +139,17 @@ pub fn find_and_report_envs(
139139
.insert("Path", start.elapsed());
140140
});
141141
// Step 3: Search in some global locations for virtual envs.
142-
let environment_directories_search = environment_directories.clone();
143-
s.spawn(|| {
142+
// Convert to Arc<[PathBuf]> for O(1) cloning in thread spawns
143+
let environment_directories: Arc<[PathBuf]> = environment_directories.into();
144+
let environment_directories_for_step3 = environment_directories.clone();
145+
let summary_for_step3 = summary.clone();
146+
s.spawn(move || {
144147
let start = std::time::Instant::now();
145148
if search_global {
146149
let mut possible_environments = vec![];
147150

148151
// These are directories that contain environments, hence enumerate these directories.
149-
for directory in environment_directories_search {
152+
for directory in environment_directories_for_step3.iter() {
150153
if let Ok(reader) = fs::read_dir(directory) {
151154
possible_environments.append(
152155
&mut reader
@@ -177,14 +180,14 @@ pub fn find_and_report_envs(
177180
);
178181

179182
find_python_environments(
180-
search_paths,
183+
&search_paths,
181184
reporter,
182185
locators,
183186
false,
184187
&global_env_search_paths,
185188
);
186189
}
187-
summary
190+
summary_for_step3
188191
.lock()
189192
.unwrap()
190193
.breakdown
@@ -197,7 +200,8 @@ pub fn find_and_report_envs(
197200
// This list of folders generally map to workspace folders
198201
// & users can have a lot of workspace folders and can have a large number fo files/directories
199202
// that could the discovery.
200-
s.spawn(|| {
203+
let summary_for_step4 = summary.clone();
204+
s.spawn(move || {
201205
let start = std::time::Instant::now();
202206
thread::scope(|s| {
203207
// Find environments in the workspace folders.
@@ -206,8 +210,9 @@ pub fn find_and_report_envs(
206210
"Searching for environments in workspace folders: {:?}",
207211
workspace_directories
208212
);
209-
let global_env_search_paths: Vec<PathBuf> =
210-
get_search_paths_from_env_variables(environment);
213+
// Convert to Arc<[PathBuf]> for O(1) cloning in thread spawns
214+
let global_env_search_paths: Arc<[PathBuf]> =
215+
get_search_paths_from_env_variables(environment).into();
211216
for workspace_folder in workspace_directories {
212217
let global_env_search_paths = global_env_search_paths.clone();
213218
let environment_directories = environment_directories.clone();
@@ -236,7 +241,7 @@ pub fn find_and_report_envs(
236241
}
237242
});
238243

239-
summary
244+
summary_for_step4
240245
.lock()
241246
.unwrap()
242247
.breakdown
@@ -277,7 +282,7 @@ pub fn find_python_environments_in_workspace_folder_recursive(
277282

278283
// Possible this is an environment.
279284
find_python_environments_in_paths_with_locators(
280-
paths_to_search_first.clone(),
285+
&paths_to_search_first,
281286
locators,
282287
reporter,
283288
true,
@@ -309,13 +314,13 @@ pub fn find_python_environments_in_workspace_folder_recursive(
309314
})
310315
.filter(|p| !paths_to_search_first.contains(p))
311316
{
312-
find_python_environments(vec![folder], reporter, locators, true, &[]);
317+
find_python_environments(&[folder], reporter, locators, true, &[]);
313318
}
314319
}
315320
}
316321

317322
fn find_python_environments(
318-
paths: Vec<PathBuf>,
323+
paths: &[PathBuf],
319324
reporter: &dyn Reporter,
320325
locators: &Arc<Vec<Arc<dyn Locator>>>,
321326
is_workspace_folder: bool,
@@ -327,9 +332,10 @@ fn find_python_environments(
327332
thread::scope(|s| {
328333
for item in paths {
329334
let locators = locators.clone();
335+
let item = item.clone();
330336
s.spawn(move || {
331337
find_python_environments_in_paths_with_locators(
332-
vec![item],
338+
&[item],
333339
&locators,
334340
reporter,
335341
is_workspace_folder,
@@ -341,7 +347,7 @@ fn find_python_environments(
341347
}
342348

343349
fn find_python_environments_in_paths_with_locators(
344-
paths: Vec<PathBuf>,
350+
paths: &[PathBuf],
345351
locators: &Arc<Vec<Arc<dyn Locator>>>,
346352
reporter: &dyn Reporter,
347353
is_workspace_folder: bool,
@@ -356,15 +362,15 @@ fn find_python_environments_in_paths_with_locators(
356362

357363
// Paths like /Library/Frameworks/Python.framework/Versions/3.10/bin can end up in the current PATH variable.
358364
// Hence do not just look for files in a bin directory of the path.
359-
if let Some(executable) = find_executable(&path) {
365+
if let Some(executable) = find_executable(path) {
360366
vec![executable]
361367
} else {
362368
vec![]
363369
}
364370
} else {
365371
// Paths like /Library/Frameworks/Python.framework/Versions/3.10/bin can end up in the current PATH variable.
366372
// Hence do not just look for files in a bin directory of the path.
367-
find_executables(path)
373+
find_executables(path.clone())
368374
.into_iter()
369375
.filter(|p| {
370376
// Exclude python2 on macOS

0 commit comments

Comments
 (0)