Skip to main content

moirai_utils/
lib.rs

1//! Utility functions and data structures for Moirai concurrency library.
2//!
3//! This crate provides modular utility components organized by domain:
4//!
5//! - [`cache`] - Cache alignment utilities for performance optimization
6//! - [`atomic`] - Atomic operations and counters for lock-free programming
7//! - [`queue`] - Lock-free queues for high-performance data structures
8//! - [`result_cell`] - One-shot completion cell shared by the task and async handles
9//! - [`memory`] - Memory utilities for cache prefetching
10
11#![cfg_attr(not(feature = "std"), no_std)]
12#![deny(missing_docs)]
13
14#[cfg(feature = "std")]
15extern crate std;
16
17#[cfg(not(feature = "std"))]
18extern crate alloc;
19
20// Modular organization following SOC and domain-oriented design
21pub mod atomic;
22pub mod cache;
23pub mod memory;
24pub mod queue;
25pub mod result_cell;
26
27// SIMD optimizations for high-performance computing
28#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
29pub mod simd;
30
31// Re-export commonly used types for convenience
32pub use atomic::AtomicCounter;
33pub use cache::{
34    CACHE_LINE_SIZE, CacheAligned, CachePad, DESTRUCTIVE_INTERFERENCE_SIZE, align_to_cache_line,
35};
36pub use memory::{prefetch_read, prefetch_write};
37pub use queue::LockFreeQueue;
38pub use result_cell::{ResultCell, Waiter};
39
40// SIMD optimization counter and scalar contracts for performance tracking.
41#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
42pub use simd::{SimdReal, SimdScalar, has_native_vector_path};
43
44#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
45use std::sync::OnceLock;
46
47#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
48static GLOBAL_SIMD_COUNTER: OnceLock<SimdCounter> = OnceLock::new();
49
50/// Get the global SIMD performance counter instance.
51///
52/// This provides a singleton counter for tracking SIMD vs scalar operation usage
53/// across the entire application.
54#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
55pub fn global_simd_counter() -> &'static SimdCounter {
56    GLOBAL_SIMD_COUNTER.get_or_init(SimdCounter::new)
57}
58
59/// Performance counter for tracking SIMD optimization usage.
60///
61/// This counter tracks the ratio of vectorized vs scalar operations
62/// to help optimize performance-critical code paths.
63#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
64#[derive(Debug)]
65pub struct SimdCounter {
66    vectorized_ops: AtomicCounter,
67    scalar_ops: AtomicCounter,
68    vectorized_elements: AtomicCounter,
69    scalar_elements: AtomicCounter,
70}
71
72#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
73impl SimdCounter {
74    /// Create a new SIMD performance counter.
75    pub fn new() -> Self {
76        Self {
77            vectorized_ops: AtomicCounter::new(),
78            scalar_ops: AtomicCounter::new(),
79            vectorized_elements: AtomicCounter::new(),
80            scalar_elements: AtomicCounter::new(),
81        }
82    }
83
84    /// Record a vectorized operation with the number of elements processed.
85    pub fn record_vectorized_op(&self, elements: usize) {
86        self.vectorized_ops.increment();
87        self.vectorized_elements.add(elements);
88    }
89
90    /// Record a scalar operation with the number of elements processed.
91    pub fn record_scalar_op(&self, elements: usize) {
92        self.scalar_ops.increment();
93        self.scalar_elements.add(elements);
94    }
95
96    /// Get the total number of vectorized operations performed.
97    pub fn vectorized_ops(&self) -> usize {
98        self.vectorized_ops.get()
99    }
100
101    /// Get the total number of scalar operations performed.
102    pub fn scalar_ops(&self) -> usize {
103        self.scalar_ops.get()
104    }
105
106    /// Calculate the vectorization rate as a fraction of total operations.
107    pub fn vectorization_rate(&self) -> f64 {
108        let total = self.vectorized_ops() + self.scalar_ops();
109        if total == 0 {
110            0.0
111        } else {
112            self.vectorized_ops() as f64 / total as f64
113        }
114    }
115
116    /// Get basic statistics about SIMD usage.
117    pub fn get_stats(&self) -> (usize, usize, usize, usize) {
118        (
119            self.vectorized_ops(),
120            self.scalar_ops(),
121            self.vectorized_elements.get(),
122            self.scalar_elements.get(),
123        )
124    }
125
126    /// Reset all counters to zero.
127    pub fn reset(&self) {
128        self.vectorized_ops.reset();
129        self.scalar_ops.reset();
130        self.vectorized_elements.reset();
131        self.scalar_elements.reset();
132    }
133}
134
135#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
136impl Default for SimdCounter {
137    fn default() -> Self {
138        Self::new()
139    }
140}
141
142#[cfg(test)]
143mod integration_tests {
144    use super::*;
145
146    #[test]
147    fn test_modular_integration() {
148        // Test that all modules work together
149        let aligned_data = CacheAligned::new(42);
150        assert_eq!(*aligned_data, 42);
151
152        let counter = AtomicCounter::new();
153        counter.increment();
154        assert_eq!(counter.get(), 1);
155
156        let queue = LockFreeQueue::<i32>::with_capacity(4);
157        queue.enqueue(1);
158        assert_eq!(queue.try_dequeue(), Some(1));
159    }
160}