moirai_core/executor/config.rs
1//! Configuration settings for executor behavior.
2
3use crate::platform::String;
4
5// Memory pool size constants
6const KILOBYTE: usize = 1024;
7const MEGABYTE: usize = 1024 * KILOBYTE;
8/// Default capacity for the small object allocation pool.
9pub const SMALL_POOL_SIZE: usize = 64 * KILOBYTE;
10/// Default capacity for the medium object allocation pool.
11pub const MEDIUM_POOL_SIZE: usize = MEGABYTE;
12/// Default capacity for the large object allocation pool.
13pub const LARGE_POOL_SIZE: usize = 16 * MEGABYTE;
14
15/// Default bound for the global task queue (tasks, not bytes). Sized for
16/// burst absorption across all workers before producers observe backpressure.
17pub const DEFAULT_GLOBAL_QUEUE_CAPACITY: usize = 8192;
18/// Default bound for each worker's local queue (tasks, not bytes). Small so
19/// idle workers can steal instead of one worker hoarding a deep queue.
20pub const DEFAULT_LOCAL_QUEUE_CAPACITY: usize = 256;
21
22/// Configuration settings for executor behavior and performance characteristics.
23///
24/// This struct encapsulates all tunable parameters that affect executor operation,
25/// including thread pool sizes, queue capacities, and various performance optimizations.
26#[allow(clippy::module_name_repetitions)]
27pub struct ExecutorConfig {
28 /// Number of worker threads for parallel tasks
29 pub worker_threads: usize,
30 /// Number of threads dedicated to async tasks
31 pub async_threads: usize,
32 /// Maximum size of the global task queue
33 pub max_global_queue_size: usize,
34 /// Maximum size of per-thread local queues
35 pub max_local_queue_size: usize,
36 /// Thread name prefix for worker threads
37 pub thread_name_prefix: String,
38 /// Whether to enable NUMA-aware thread placement
39 #[cfg(feature = "numa")]
40 pub numa_aware: bool,
41 /// Whether to enable metrics collection
42 #[cfg(feature = "metrics")]
43 pub enable_metrics: bool,
44 /// Task preemption configuration
45 pub preemption: PreemptionConfig,
46 /// Memory management configuration
47 pub memory: MemoryConfig,
48 /// Task cleanup configuration
49 pub cleanup: CleanupConfig,
50}
51
52impl Default for ExecutorConfig {
53 fn default() -> Self {
54 Self {
55 worker_threads: super::num_cpus(),
56 async_threads: (super::num_cpus() / 4).max(1),
57 max_global_queue_size: DEFAULT_GLOBAL_QUEUE_CAPACITY,
58 max_local_queue_size: DEFAULT_LOCAL_QUEUE_CAPACITY,
59 thread_name_prefix: "moirai-worker".into(),
60 #[cfg(feature = "numa")]
61 numa_aware: true,
62 #[cfg(feature = "metrics")]
63 enable_metrics: true,
64 preemption: PreemptionConfig::default(),
65 memory: MemoryConfig::default(),
66 cleanup: CleanupConfig::default(),
67 }
68 }
69}
70
71/// Configuration for task preemption.
72#[derive(Debug, Clone)]
73pub struct PreemptionConfig {
74 /// Whether to enable cooperative preemption
75 pub enabled: bool,
76 /// Time slice for each task before preemption (microseconds)
77 pub time_slice_us: u64,
78 /// Whether to preempt based on priority
79 pub priority_based: bool,
80 /// Minimum execution time before preemption (microseconds)
81 pub min_execution_time_us: u64,
82}
83
84impl Default for PreemptionConfig {
85 fn default() -> Self {
86 Self {
87 enabled: true,
88 time_slice_us: 10_000, // 10ms
89 priority_based: true,
90 min_execution_time_us: 1_000, // 1ms
91 }
92 }
93}
94
95/// Configuration for memory management.
96#[derive(Debug, Clone)]
97pub struct MemoryConfig {
98 /// Whether to use memory pools
99 pub use_memory_pools: bool,
100 /// Size of small object pool (bytes)
101 pub small_pool_size: usize,
102 /// Size of medium object pool (bytes)
103 pub medium_pool_size: usize,
104 /// Size of large object pool (bytes)
105 pub large_pool_size: usize,
106 /// Whether to track memory usage per task
107 pub track_per_task_memory: bool,
108}
109
110impl Default for MemoryConfig {
111 fn default() -> Self {
112 Self {
113 use_memory_pools: true,
114 small_pool_size: SMALL_POOL_SIZE,
115 medium_pool_size: MEDIUM_POOL_SIZE,
116 large_pool_size: LARGE_POOL_SIZE,
117 track_per_task_memory: cfg!(feature = "metrics"),
118 }
119 }
120}
121
122/// Configuration for task metadata cleanup.
123///
124/// Controls how and when completed task metadata is removed from memory
125/// to prevent memory leaks in long-running executors.
126#[derive(Debug, Clone)]
127pub struct CleanupConfig {
128 /// How long to keep completed task metadata before cleanup
129 ///
130 /// # Default: 5 minutes
131 /// # Range: 1 second to `task_retention_duration`
132 pub task_retention_duration: core::time::Duration,
133
134 /// How often to run the cleanup process
135 ///
136 /// # Default: 30 seconds
137 /// # Range: 1 second to `task_retention_duration`
138 pub cleanup_interval: core::time::Duration,
139
140 /// Whether to enable automatic cleanup
141 ///
142 /// If disabled, cleanup must be triggered manually via `cleanup_completed_tasks()`
143 /// # Default: true
144 pub enable_automatic_cleanup: bool,
145
146 /// Maximum number of completed tasks to retain regardless of age
147 ///
148 /// This provides a hard limit to prevent unbounded memory growth
149 /// # Default: 10,000 tasks
150 pub max_retained_tasks: usize,
151}
152
153impl Default for CleanupConfig {
154 fn default() -> Self {
155 Self {
156 task_retention_duration: core::time::Duration::from_mins(5),
157 cleanup_interval: core::time::Duration::from_secs(30), // 30 seconds
158 enable_automatic_cleanup: true,
159 max_retained_tasks: 10_000,
160 }
161 }
162}