Skip to content

Commit 07c807d

Browse files
committed
Auto merge of #536 - pietroalbini:cleanup-caches, r=Mark-Simulacrum
Purge caches before starting an experiment when out of disk space This PR changes the agent to purge all caches before starting an experiment if there is less than half disk space free on the host machine. This will make running Crater on "low" disk space hosts way less painful. In theory this only runs the cleanup code when an experiment finishes, but in practice it will run it every 1000 built crates, since distributed runs works internally by splitting an experiment in 1000 crates chunks. r? @Mark-Simulacrum
2 parents a4a29da + 957fca5 commit 07c807d

File tree

7 files changed

+103
-53
lines changed

7 files changed

+103
-53
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ hmac = "0.7"
6363
sha-1 = "0.8"
6464
rust_team_data = { git = "https://github.com/rust-lang/team" }
6565
systemstat = "0.1.4"
66-
rustwide = { version = "0.8.0", features = ["unstable"] }
66+
rustwide = { version = "0.10.0", features = ["unstable", "unstable-toolchain-ci"] }
6767
percent-encoding = "2.1.0"
6868
remove_dir_all = "0.5.2"
6969
ctrlc = "3.1.3"

src/agent/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::db::{Database, QueryUtils};
99
use crate::experiments::Experiment;
1010
use crate::prelude::*;
1111
use crate::utils;
12+
use crate::utils::disk_usage::DiskUsage;
1213
use failure::Error;
1314
use rustwide::Workspace;
1415
use std::collections::BTreeSet;
@@ -17,6 +18,9 @@ use std::ops;
1718
use std::thread;
1819
use std::time::Duration;
1920

21+
// Purge all the caches if the disk is more than 50% full.
22+
const PURGE_CACHES_THRESHOLD: f32 = 0.5;
23+
2024
#[derive(Default, Serialize, Deserialize)]
2125
pub struct Capabilities {
2226
#[serde(default)]
@@ -117,6 +121,18 @@ fn run_experiment(
117121
}
118122
*past_experiment = Some(ex.name.clone());
119123

124+
match DiskUsage::fetch() {
125+
Ok(usage) => {
126+
if usage.is_threshold_reached(PURGE_CACHES_THRESHOLD) {
127+
warn!("purging all caches");
128+
workspace.purge_all_caches().map_err(|err| (None, err))?;
129+
}
130+
}
131+
Err(err) => {
132+
warn!("failed to check the disk usage: {}", err);
133+
}
134+
}
135+
120136
crate::runner::run_ex(&ex, workspace, &crates, db, threads_count, &agent.config)
121137
.map_err(|err| (Some(ex), err))?;
122138
Ok(())

src/runner/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ fn run_cargo<DB: WriteResults>(
167167
} else if !error_codes.is_empty() {
168168
Err(e.context(FailureReason::CompilerError(error_codes)).into())
169169
} else {
170-
Err(e)
170+
Err(e.into())
171171
}
172172
}
173173
}

src/runner/worker.rs

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ use crate::runner::{OverrideResult, RunnerState};
77
use crate::utils;
88
use rustwide::{BuildDirectory, Workspace};
99
use std::collections::HashMap;
10-
use std::path::Path;
1110
use std::sync::{
1211
atomic::{AtomicBool, Ordering},
1312
mpsc::{self, RecvTimeoutError},
1413
Arc, Mutex,
1514
};
1615
use std::thread;
1716
use std::time::Duration;
18-
use systemstat::{Filesystem, Platform, System};
1917

2018
pub(super) struct Worker<'a, DB: WriteResults + Sync> {
2119
name: String,
@@ -185,54 +183,21 @@ impl<'a, DB: WriteResults + Sync> DiskSpaceWatcher<'a, DB> {
185183
}
186184

187185
fn check(&self) -> Fallible<()> {
188-
let fs = match self.current_mount() {
189-
Ok(fs) => fs,
190-
Err(e) => {
186+
let usage = match crate::utils::disk_usage::DiskUsage::fetch() {
187+
Ok(usage) => usage,
188+
Err(err) => {
191189
// TODO: `current_mount` fails sometimes on Windows with ERROR_DEVICE_NOT_READY.
192-
warn!("Failed to check space remaining: {}", e);
190+
warn!("Failed to check space remaining: {}", err);
193191
return Ok(());
194192
}
195193
};
196194

197-
let usage = (fs.total.as_usize() - fs.free.as_usize()) as f32 / fs.total.as_usize() as f32;
198-
if usage < self.threshold {
199-
info!(
200-
"{} disk usage at {}%",
201-
fs.fs_mounted_on,
202-
(usage * 100.0) as u8
203-
);
204-
} else {
205-
warn!(
206-
"{} disk usage at {}%, which is over the threshold of {}%",
207-
fs.fs_mounted_on,
208-
(usage * 100.0) as u8,
209-
(self.threshold * 100.0) as u8,
210-
);
211-
195+
if usage.is_threshold_reached(self.threshold) {
196+
warn!("running the scheduled thread cleanup");
212197
for worker in self.workers {
213198
worker.schedule_target_dir_cleanup();
214199
}
215-
warn!("scheduled cleanup");
216200
}
217201
Ok(())
218202
}
219-
220-
fn current_mount(&self) -> Fallible<Filesystem> {
221-
let current_dir = crate::utils::path::normalize_path(&crate::dirs::WORK_DIR);
222-
let system = System::new();
223-
224-
let mut found = None;
225-
let mut found_pos = std::usize::MAX;
226-
for mount in system.mounts()?.into_iter() {
227-
let path = Path::new(&mount.fs_mounted_on);
228-
for (i, ancestor) in current_dir.ancestors().enumerate() {
229-
if ancestor == path && i < found_pos {
230-
found_pos = i;
231-
found = Some(mount);
232-
break;
233-
}
234-
}
235-
}
236-
found.ok_or_else(|| failure::err_msg("failed to find the current mount"))
237-
}
238203
}

src/utils/disk_usage.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use crate::prelude::*;
2+
use std::path::Path;
3+
use systemstat::{Filesystem, Platform, System};
4+
5+
pub(crate) struct DiskUsage {
6+
mount_point: String,
7+
usage: f32,
8+
}
9+
10+
impl DiskUsage {
11+
pub(crate) fn fetch() -> Fallible<Self> {
12+
let fs = current_mount()?;
13+
Ok(Self {
14+
mount_point: fs.fs_mounted_on.clone(),
15+
usage: (fs.total.as_usize() - fs.free.as_usize()) as f32 / fs.total.as_usize() as f32,
16+
})
17+
}
18+
19+
pub(crate) fn is_threshold_reached(&self, threshold: f32) -> bool {
20+
let usage = (self.usage * 100.0) as u8;
21+
if self.usage < threshold {
22+
info!("{} disk usage at {}%", self.mount_point, usage);
23+
false
24+
} else {
25+
warn!(
26+
"{} disk usage at {}%, which is over the threshold of {}%",
27+
self.mount_point,
28+
usage,
29+
(threshold * 100.0) as u8
30+
);
31+
true
32+
}
33+
}
34+
}
35+
36+
fn current_mount() -> Fallible<Filesystem> {
37+
let current_dir = crate::utils::path::normalize_path(&crate::dirs::WORK_DIR);
38+
let system = System::new();
39+
40+
let mut found = None;
41+
let mut found_pos = std::usize::MAX;
42+
for mount in system.mounts()?.into_iter() {
43+
let path = Path::new(&mount.fs_mounted_on);
44+
for (i, ancestor) in current_dir.ancestors().enumerate() {
45+
if ancestor == path && i < found_pos {
46+
found_pos = i;
47+
found = Some(mount);
48+
break;
49+
}
50+
}
51+
}
52+
found.ok_or_else(|| failure::err_msg("failed to find the current mount"))
53+
}

src/utils/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub(crate) mod hex;
99
pub(crate) mod http;
1010
#[macro_use]
1111
mod macros;
12+
pub(crate) mod disk_usage;
1213
pub(crate) mod path;
1314
pub(crate) mod serialize;
1415
pub mod size;

0 commit comments

Comments
 (0)