#![allow(clippy::expect_used, clippy::print_stderr, clippy::print_stdout)]
use std::path::{Path, PathBuf};
use std::process::ExitCode;
use lean_rs_worker::{LeanWorker, LeanWorkerConfig, LeanWorkerRestartPolicy};
const DEFAULT_IMPORTS: u64 = 8;
const DEFAULT_MAX_IMPORTS: u64 = 2;
fn main() -> ExitCode {
match run() {
Ok(()) => ExitCode::SUCCESS,
Err(err) => {
eprintln!("{err}");
ExitCode::FAILURE
}
}
}
fn run() -> Result<(), Box<dyn std::error::Error>> {
let imports = env_u64("LEAN_RS_WORKER_MEMORY_IMPORTS", DEFAULT_IMPORTS);
let max_imports = env_u64("LEAN_RS_WORKER_MEMORY_MAX_IMPORTS", DEFAULT_MAX_IMPORTS);
let fixture = fixture_root();
lean_toolchain::build_lake_target_quiet(&fixture, "LeanRsFixture")?;
let worker_binary = worker_binary()?;
let policy = LeanWorkerRestartPolicy::default()
.max_imports(max_imports)
.max_rss_kib(u64::MAX);
let mut worker = LeanWorker::spawn(&LeanWorkerConfig::new(worker_binary).restart_policy(policy))?;
println!("workload=worker_memory_cycling");
println!("platform={} {}", std::env::consts::OS, std::env::consts::ARCH);
println!("imports={imports}");
println!("max_imports_per_child={max_imports}");
for iteration in 1..=imports {
let value = worker.call_fixture_mul(&fixture, iteration, 2)?;
let rss = worker.rss_kib();
let stats = worker.stats();
println!(
"iteration={iteration} value={value} requests={} imports={} restarts={} exits={} rss_kib={} last_reason={:?}",
stats.requests,
stats.imports,
stats.restarts,
stats.exits,
stats
.last_rss_kib
.or(rss)
.map_or_else(|| "unavailable".to_owned(), |value| value.to_string()),
stats.last_restart_reason
);
}
let stats = worker.stats();
println!(
"summary requests={} imports={} restarts={} exits={} rss_unavailable={}",
stats.requests, stats.imports, stats.restarts, stats.exits, stats.rss_samples_unavailable
);
let exit = worker.terminate()?;
println!("worker_exit_success={}", exit.success);
println!("status=ok");
Ok(())
}
fn env_u64(name: &str, default: u64) -> u64 {
std::env::var(name)
.ok()
.and_then(|value| value.parse::<u64>().ok())
.unwrap_or(default)
}
fn worker_binary() -> Result<PathBuf, Box<dyn std::error::Error>> {
let current = std::env::current_exe()?;
let profile_dir = current
.parent()
.and_then(Path::parent)
.ok_or("example binary is not under target/<profile>/examples")?;
let binary = profile_dir.join(format!("lean-rs-worker-child{}", std::env::consts::EXE_SUFFIX));
if !binary.exists() {
return Err(format!(
"worker child binary not found at {}; run `cargo build -p lean-rs-worker --bin lean-rs-worker-child` first",
binary.display()
)
.into());
}
Ok(binary)
}
fn fixture_root() -> PathBuf {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest_dir.parent().and_then(Path::parent).map_or_else(
|| PathBuf::from("fixtures/lean"),
|workspace| workspace.join("fixtures").join("lean"),
)
}