pub mod cache;
pub mod metrics;
pub mod profiler;
pub use cache::{CacheManager, CacheStats};
pub use metrics::{MetricsCollector, PerformanceMetrics};
pub use profiler::{Profiler, ProfilerGuard};
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct PerformanceConfig {
pub enable_monitoring: bool,
pub enable_caching: bool,
pub cache_size_mb: usize,
pub cache_ttl_seconds: u64,
pub enable_profiling: bool,
pub max_metrics_history: usize,
}
impl Default for PerformanceConfig {
fn default() -> Self {
Self {
enable_monitoring: true,
enable_caching: true,
cache_size_mb: 100,
cache_ttl_seconds: 300, enable_profiling: false, max_metrics_history: 1000,
}
}
}
pub struct Timer {
start: Instant,
name: String,
}
impl Timer {
pub fn new(name: impl Into<String>) -> Self {
Self {
start: Instant::now(),
name: name.into(),
}
}
pub fn elapsed(&self) -> Duration {
self.start.elapsed()
}
pub fn elapsed_ms(&self) -> u64 {
self.elapsed().as_millis() as u64
}
pub fn name(&self) -> &str {
&self.name
}
}
impl Drop for Timer {
fn drop(&mut self) {
let elapsed = self.elapsed_ms();
if elapsed > 100 {
tracing::warn!("Slow operation '{}' took {}ms", self.name, elapsed);
} else {
tracing::debug!("Operation '{}' took {}ms", self.name, elapsed);
}
}
}
#[macro_export]
macro_rules! time_operation {
($name:expr, $block:block) => {{
let _timer = $crate::performance::Timer::new($name);
$block
}};
}
#[macro_export]
macro_rules! time_async_operation {
($name:expr, $block:block) => {{
let _timer = $crate::performance::Timer::new($name);
$block
}};
}
#[derive(Debug, Clone)]
pub enum OptimizationHint {
Cache { key: String, ttl_seconds: u64 },
Parallelize { max_concurrency: usize },
Incremental { checkpoint_interval: usize },
Debounce { delay_ms: u64 },
}
#[derive(Debug, Clone)]
pub struct SystemPerformanceStats {
pub total_operations: u64,
pub avg_operation_time_ms: f64,
pub cache_hits: u64,
pub cache_misses: u64,
pub cache_hit_ratio: f64,
pub memory_usage_mb: f64,
pub active_profiles: usize,
}
impl SystemPerformanceStats {
pub fn new() -> Self {
Self {
total_operations: 0,
avg_operation_time_ms: 0.0,
cache_hits: 0,
cache_misses: 0,
cache_hit_ratio: 0.0,
memory_usage_mb: 0.0,
active_profiles: 0,
}
}
pub fn update_cache_stats(&mut self, hits: u64, misses: u64) {
self.cache_hits = hits;
self.cache_misses = misses;
let total = hits + misses;
self.cache_hit_ratio = if total > 0 {
hits as f64 / total as f64
} else {
0.0
};
}
pub fn update_operation_stats(&mut self, total_ops: u64, avg_time_ms: f64) {
self.total_operations = total_ops;
self.avg_operation_time_ms = avg_time_ms;
}
pub fn update_memory_usage(&mut self, usage_mb: f64) {
self.memory_usage_mb = usage_mb;
}
pub fn update_active_profiles(&mut self, count: usize) {
self.active_profiles = count;
}
}
impl Default for SystemPerformanceStats {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread;
use std::time::Duration;
#[test]
fn test_timer_creation() {
let timer = Timer::new("test_operation");
assert_eq!(timer.name(), "test_operation");
assert!(timer.elapsed().as_nanos() > 0);
}
#[test]
fn test_timer_elapsed() {
let timer = Timer::new("test");
thread::sleep(Duration::from_millis(10));
assert!(timer.elapsed_ms() >= 10);
}
#[test]
fn test_performance_config_default() {
let config = PerformanceConfig::default();
assert!(config.enable_monitoring);
assert!(config.enable_caching);
assert_eq!(config.cache_size_mb, 100);
assert_eq!(config.cache_ttl_seconds, 300);
assert!(!config.enable_profiling);
assert_eq!(config.max_metrics_history, 1000);
}
#[test]
fn test_system_performance_stats() {
let mut stats = SystemPerformanceStats::new();
stats.update_cache_stats(80, 20);
assert_eq!(stats.cache_hits, 80);
assert_eq!(stats.cache_misses, 20);
assert_eq!(stats.cache_hit_ratio, 0.8);
stats.update_operation_stats(1000, 25.5);
assert_eq!(stats.total_operations, 1000);
assert_eq!(stats.avg_operation_time_ms, 25.5);
stats.update_memory_usage(150.5);
assert_eq!(stats.memory_usage_mb, 150.5);
stats.update_active_profiles(3);
assert_eq!(stats.active_profiles, 3);
}
#[test]
fn test_cache_hit_ratio_calculation() {
let mut stats = SystemPerformanceStats::new();
stats.update_cache_stats(0, 0);
assert_eq!(stats.cache_hit_ratio, 0.0);
stats.update_cache_stats(100, 0);
assert_eq!(stats.cache_hit_ratio, 1.0);
stats.update_cache_stats(0, 100);
assert_eq!(stats.cache_hit_ratio, 0.0);
stats.update_cache_stats(75, 25);
assert_eq!(stats.cache_hit_ratio, 0.75);
}
#[tokio::test]
async fn test_time_operation_macro() {
let result = time_operation!("test_macro", {
thread::sleep(Duration::from_millis(1));
42
});
assert_eq!(result, 42);
}
#[tokio::test]
async fn test_time_async_operation_macro() {
let result = time_async_operation!("test_async_macro", {
tokio::time::sleep(Duration::from_millis(1)).await;
"hello"
});
assert_eq!(result, "hello");
}
}