use std::num::NonZeroUsize;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RuntimeConfig {
pub worker_threads: usize,
pub max_blocking_threads: usize,
pub compute_threads: usize,
pub io_threads: usize,
}
impl RuntimeConfig {
pub fn auto() -> Self {
let cores = available_parallelism();
Self {
worker_threads: cores,
max_blocking_threads: cores.saturating_add(cores / 2).max(4),
compute_threads: cores,
io_threads: cores.saturating_div(2).clamp(1, 8),
}
}
pub fn from_cores(cores: usize) -> Self {
let cores = cores.max(1);
Self {
worker_threads: cores,
max_blocking_threads: cores.saturating_add(cores / 2).max(4),
compute_threads: cores,
io_threads: cores.saturating_div(2).clamp(1, 8),
}
}
pub fn compact() -> Self {
let cores = available_parallelism();
Self {
worker_threads: cores.max(2),
max_blocking_threads: 2,
compute_threads: 1,
io_threads: 1,
}
}
}
pub fn available_parallelism() -> usize {
std::thread::available_parallelism()
.map(NonZeroUsize::get)
.unwrap_or(1)
}
#[cfg(feature = "compute")]
pub fn build_rayon_pool(config: &RuntimeConfig) -> rayon::ThreadPool {
rayon::ThreadPoolBuilder::new()
.num_threads(config.compute_threads)
.thread_name(|i| format!("mytheclipse-compute-{i}"))
.build()
.expect("failed to build rayon compute pool")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn auto_is_nonzero() {
let c = RuntimeConfig::auto();
assert!(c.worker_threads >= 1);
assert!(c.max_blocking_threads >= 4);
assert!(c.compute_threads >= 1);
assert!(c.io_threads >= 1);
assert!(c.io_threads <= 8);
}
#[test]
fn from_cores_clamps() {
let c = RuntimeConfig::from_cores(4);
assert_eq!(c.worker_threads, 4);
assert_eq!(c.max_blocking_threads, 6);
let one = RuntimeConfig::from_cores(0);
assert_eq!(one.worker_threads, 1);
}
#[test]
fn compact_is_minimal() {
let c = RuntimeConfig::compact();
assert_eq!(c.compute_threads, 1);
assert_eq!(c.io_threads, 1);
}
}