Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions glidefs/src/bin/boot_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ async fn main() -> anyhow::Result<()> {
timeout,
static_seed: Vec::new(),
max_blocks,
scratch_dir: None,
};
let boot_set = capture_boot_blocks_served(
Arc::clone(&content_store),
Expand Down
11 changes: 10 additions & 1 deletion glidefs/src/block/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2241,6 +2241,9 @@ impl ExportRouter {
let router = Arc::clone(self);
let content_store = self.content_store_for_prefix(s3_prefix);
let name_owned = name.to_string();
// Profiler scratch lands under the daemon's on-disk cache dir, never a
// tmpfs /tmp (foyer clean-cache regions would otherwise run in RAM).
let scratch_dir = self.cache_dir.clone();
let cleanup_key = key;
let _handle = spawn_supervised("profile-bg", async move {
// Guard removes the profile_tasks entry on any exit (return,
Expand Down Expand Up @@ -2275,7 +2278,13 @@ impl ExportRouter {
force: params.force,
max_blocks: params.max_blocks,
};
match crate::oci::profile_runner::profile_base(content_store, &profile_cfg, spec).await
match crate::oci::profile_runner::profile_base(
content_store,
&profile_cfg,
spec,
Some(scratch_dir),
)
.await
{
Ok(crate::oci::profile_runner::ProfileOutcome::UpToDate { .. }) => {
info!(name = %name_owned, "profile: boot set already up to date");
Expand Down
1 change: 1 addition & 0 deletions glidefs/src/cli/bless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ fn profiling_opts(settings: &Settings, static_seed: Vec<String>) -> Result<BootP
timeout: profile_timeout(),
static_seed,
max_blocks: 200_000,
scratch_dir: None,
})
}

Expand Down
2 changes: 1 addition & 1 deletion glidefs/src/cli/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub async fn run_profile(args: ProfileArgs) -> Result<()> {
max_blocks: args.max_blocks,
};

match profile_base(content_store, &pcfg, spec).await? {
match profile_base(content_store, &pcfg, spec, None).await? {
ProfileOutcome::UpToDate { fingerprint } => {
println!(
"Boot set for '{}' is up to date (fingerprint {}); skipping. Use --force to re-profile.",
Expand Down
21 changes: 20 additions & 1 deletion glidefs/src/oci/boot_capture_served.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ pub struct BootProfileOptions {
pub static_seed: Vec<String>,
/// Cap on captured blocks per run.
pub max_blocks: usize,
/// Parent directory for the per-run scratch (write cache + foyer clean
/// cache). `None` falls back to `std::env::temp_dir()`.
///
/// The long-lived daemon MUST set this to a real on-disk path (e.g. the
/// configured `[cache].dir`): `std::env::temp_dir()` is `/tmp`, which is a
/// tmpfs on many hosts, so the profiler's disk cache would otherwise run in
/// RAM. Setting it here makes placement correct by construction, regardless
/// of whether `$TMPDIR` is exported in the unit. Short-lived CLI callers can
/// leave it `None` — their scratch is reclaimed when the process exits.
pub scratch_dir: Option<std::path::PathBuf>,
}

/// Rank-merge ordered block lists from multiple boot runs into one ordered union.
Expand Down Expand Up @@ -196,7 +206,16 @@ async fn capture_once(
use crate::oci::sandbox::SandboxSpec;
use tokio::sync::Notify;

let tmp = tempfile::TempDir::new().ok()?;
// Scratch (write cache + foyer clean cache) goes under `opts.scratch_dir`
// when set — keeping the profiler's disk cache off a tmpfs `/tmp`. Falls
// back to `std::env::temp_dir()` only for callers that opt out (None).
let tmp = match opts.scratch_dir.as_deref() {
Some(dir) => {
std::fs::create_dir_all(dir).ok()?;
tempfile::TempDir::new_in(dir).ok()?
}
None => tempfile::TempDir::new().ok()?,
};
let rtrace = tmp.path().join("boot.rtrace");
let tracer = Arc::new(
WriteTracer::new(
Expand Down
5 changes: 5 additions & 0 deletions glidefs/src/oci/profile_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ pub async fn profile_base(
content_store: Arc<ContentStore>,
profile_cfg: &ProfileConfig,
spec: ProfileSpec,
// Parent dir for per-run profiler scratch. The daemon passes its
// configured `[cache].dir` so the scratch lands on disk, not a tmpfs
// `/tmp`; CLI callers pass `None` (process-lifetime scratch).
scratch_dir: Option<std::path::PathBuf>,
) -> Result<ProfileOutcome> {
// --- Load the base manifest + its fingerprint (ETag) ---
let (data, etag) = content_store
Expand Down Expand Up @@ -182,6 +186,7 @@ pub async fn profile_base(
timeout: spec.timeout.max(Duration::from_secs(1)),
static_seed,
max_blocks: spec.max_blocks,
scratch_dir,
};
let blocks = capture_boot_blocks_served(
Arc::clone(&content_store),
Expand Down
Loading