Skip to content

Commit 90d3275

Browse files
committed
lintcheck: parallelize
Use rayon to figure out the threadcount and half that for core count. For each core, create a target dir that is used. Otherwise, when running multiple clippys with the same target-dir, cargo would lock the dir and prevent parallelism. This way we can run multiple clippys at the same time (on root crates) but we sacrifice cache-hits (when we already cargo-checked crate-deps).
1 parent 2f815ec commit 90d3275

File tree

3 files changed

+34
-9
lines changed

3 files changed

+34
-9
lines changed

clippy_dev/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ shell-escape = "0.1"
1919
tar = { version = "0.4.30", optional = true }
2020
toml = { version = "0.5", optional = true }
2121
ureq = { version = "2.0.0-rc3", optional = true }
22+
rayon = { version = "1.5.0", optional = true }
2223
walkdir = "2"
2324

2425
[features]
25-
lintcheck = ["flate2", "serde_json", "tar", "toml", "ureq", "serde", "fs_extra"]
26+
lintcheck = ["flate2", "serde_json", "tar", "toml", "ureq", "serde", "fs_extra", "rayon"]
2627
deny-warnings = []

clippy_dev/src/lintcheck.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ use crate::clippy_project_root;
1111

1212
use std::collections::HashMap;
1313
use std::process::Command;
14+
use std::sync::atomic::{AtomicUsize, Ordering};
1415
use std::{env, fmt, fs::write, path::PathBuf};
1516

1617
use clap::ArgMatches;
18+
use rayon::prelude::*;
1719
use serde::{Deserialize, Serialize};
1820
use serde_json::Value;
1921

@@ -215,11 +217,20 @@ impl CrateSource {
215217
impl Crate {
216218
/// Run `cargo clippy` on the `Crate` and collect and return all the lint warnings that clippy
217219
/// issued
218-
fn run_clippy_lints(&self, cargo_clippy_path: &PathBuf) -> Vec<ClippyWarning> {
219-
println!("Linting {} {}...", &self.name, &self.version);
220+
fn run_clippy_lints(
221+
&self,
222+
cargo_clippy_path: &PathBuf,
223+
target_dir_index: &AtomicUsize,
224+
thread_limit: usize,
225+
) -> Vec<ClippyWarning> {
226+
// advance the atomic index by one
227+
let idx = target_dir_index.fetch_add(1, Ordering::SeqCst);
228+
// "loop" the index within 0..thread_limit
229+
let idx = idx % thread_limit;
230+
println!("Linting {} {} in target dir {:?}", &self.name, &self.version, idx);
220231
let cargo_clippy_path = std::fs::canonicalize(cargo_clippy_path).unwrap();
221232

222-
let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir/");
233+
let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
223234

224235
let mut args = vec!["--", "--message-format=json", "--", "--cap-lints=warn"];
225236

@@ -232,7 +243,8 @@ impl Crate {
232243
}
233244

234245
let all_output = std::process::Command::new(&cargo_clippy_path)
235-
.env("CARGO_TARGET_DIR", shared_target_dir)
246+
// use the looping index to create individual target dirs
247+
.env("CARGO_TARGET_DIR", shared_target_dir.join(format!("_{:?}", idx)))
236248
// lint warnings will look like this:
237249
// src/cargo/ops/cargo_compile.rs:127:35: warning: usage of `FromIterator::from_iter`
238250
.args(&args)
@@ -454,15 +466,27 @@ pub fn run(clap_config: &ArgMatches) {
454466
.into_iter()
455467
.map(|krate| krate.download_and_extract())
456468
.filter(|krate| krate.name == only_one_crate)
457-
.map(|krate| krate.run_clippy_lints(&cargo_clippy_path))
469+
.map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &AtomicUsize::new(0), 1))
458470
.flatten()
459471
.collect()
460472
} else {
473+
let counter = std::sync::atomic::AtomicUsize::new(0);
474+
475+
// Ask rayon for cpu (actually thread)count.
476+
// Use one target dir for each cpu so that we can run N clippys in parallel.
477+
// We need to use different target dirs because cargo would lock them for a single build otherwise,
478+
// killing the parallelism. However this also means that deps will only be reused half/a
479+
// quarter of the time which might result in a longer wall clock runtime
480+
481+
// Rayon seems to return thread count so half that for core count
482+
483+
let num_threads: usize = rayon::current_num_threads() / 2;
484+
461485
// check all crates (default)
462486
crates
463-
.into_iter()
487+
.into_par_iter()
464488
.map(|krate| krate.download_and_extract())
465-
.map(|krate| krate.run_clippy_lints(&cargo_clippy_path))
489+
.map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &counter, num_threads))
466490
.flatten()
467491
.collect()
468492
};

lintcheck-logs/lintcheck_crates_logs.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
clippy 0.1.52 (bed115d55 2021-02-15)
1+
clippy 0.1.52 (2f815ecd0 2021-02-18)
22

33
cargo-0.49.0/build.rs:1:null clippy::cargo_common_metadata "package `cargo` is missing `package.categories` metadata"
44
cargo-0.49.0/build.rs:1:null clippy::cargo_common_metadata "package `cargo` is missing `package.keywords` metadata"

0 commit comments

Comments
 (0)