243 lines
9.0 KiB
Rust
243 lines
9.0 KiB
Rust
use std::sync::Arc;
|
|
use std::time::Duration;
|
|
use tokio::time::{sleep, timeout};
|
|
|
|
use crate::adaptive_pool_manager::{AdaptivePoolConfig, AdaptivePoolManager};
|
|
use crate::frame_pool::HierarchicalFramePool;
|
|
use crate::memory_monitor::MemoryMonitor;
|
|
|
|
/// Main adaptive pool system test (entry point for CLI)
|
|
pub async fn test_adaptive_pool_system() -> anyhow::Result<()> {
|
|
test_adaptive_pool_integration().await
|
|
}
|
|
|
|
/// Memory pressure stress test (entry point for CLI)
|
|
pub async fn stress_test_memory_pressure() -> anyhow::Result<()> {
|
|
stress_test_adaptive_managers().await
|
|
}
|
|
|
|
/// Integration test with monitoring (entry point for CLI)
|
|
pub async fn integration_test_adaptive_with_monitoring() -> anyhow::Result<()> {
|
|
test_memory_optimization_integration().await
|
|
}
|
|
|
|
/// Integration test for adaptive pool management system
|
|
pub async fn test_adaptive_pool_integration() -> anyhow::Result<()> {
|
|
println!("🧪 Testing Adaptive Pool Management");
|
|
println!("==================================");
|
|
|
|
// Test 1: Adaptive pool manager creation
|
|
println!("\n📋 Test 1: Adaptive Pool Manager Creation");
|
|
test_adaptive_manager_creation().await?;
|
|
|
|
// Test 2: Configuration validation
|
|
println!("\n📋 Test 2: Configuration Validation");
|
|
test_configuration_validation().await?;
|
|
|
|
println!("\n✅ All adaptive pool management tests passed!");
|
|
Ok(())
|
|
}
|
|
|
|
/// Test adaptive pool manager creation and basic functionality
|
|
async fn test_adaptive_manager_creation() -> anyhow::Result<()> {
|
|
let hierarchical_pool = Arc::new(HierarchicalFramePool::new(20));
|
|
let config = AdaptivePoolConfig::default();
|
|
|
|
let _manager = AdaptivePoolManager::new(config.clone(), hierarchical_pool.clone());
|
|
|
|
println!(" ✓ Created adaptive pool manager");
|
|
println!(" Target memory usage: {:.1}%", config.target_memory_usage * 100.0);
|
|
println!(" High pressure threshold: {:.1}%", config.high_memory_threshold * 100.0);
|
|
println!(" Min pool capacity: {}", config.min_pool_capacity);
|
|
println!(" Max pool capacity: {}", config.max_pool_capacity);
|
|
|
|
assert!(config.target_memory_usage > 0.0 && config.target_memory_usage < 1.0);
|
|
assert!(config.high_memory_threshold > config.target_memory_usage);
|
|
assert!(config.min_pool_capacity < config.max_pool_capacity);
|
|
|
|
println!(" ✓ Configuration validation passed");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test configuration validation and edge cases
|
|
async fn test_configuration_validation() -> anyhow::Result<()> {
|
|
// Test default configuration
|
|
let default_config = AdaptivePoolConfig::default();
|
|
assert!(default_config.target_memory_usage < default_config.high_memory_threshold);
|
|
assert!(default_config.high_memory_threshold < default_config.critical_memory_threshold);
|
|
|
|
println!(" ✓ Default configuration hierarchy is valid");
|
|
|
|
// Test custom configuration
|
|
let custom_config = AdaptivePoolConfig {
|
|
target_memory_usage: 0.6,
|
|
high_memory_threshold: 0.75,
|
|
critical_memory_threshold: 0.9,
|
|
min_pool_capacity: 10,
|
|
max_pool_capacity: 50,
|
|
evaluation_interval: Duration::from_secs(5),
|
|
history_samples: 20,
|
|
min_cache_hit_rate: 0.7,
|
|
};
|
|
|
|
// Validate custom config makes sense
|
|
assert!(custom_config.target_memory_usage < custom_config.high_memory_threshold);
|
|
assert!(custom_config.min_pool_capacity < custom_config.max_pool_capacity);
|
|
assert!(custom_config.min_cache_hit_rate >= 0.0 && custom_config.min_cache_hit_rate <= 1.0);
|
|
|
|
println!(" ✓ Custom configuration validation passed");
|
|
|
|
// Test with hierarchical pool
|
|
let hierarchical_pool = Arc::new(HierarchicalFramePool::new(custom_config.min_pool_capacity));
|
|
let _manager = AdaptivePoolManager::new(custom_config, hierarchical_pool);
|
|
|
|
println!(" ✓ Manager created with custom configuration");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Stress test with multiple pools and memory pressure simulation
|
|
pub async fn stress_test_adaptive_managers() -> anyhow::Result<()> {
|
|
println!("\n🚀 Stress Test: Adaptive Management Under Load");
|
|
|
|
// Create memory monitor for generating load
|
|
let memory_monitor = Arc::new(MemoryMonitor::new());
|
|
|
|
// Create hierarchical pool
|
|
let hierarchical_pool = Arc::new(HierarchicalFramePool::new(15));
|
|
|
|
// Create adaptive manager
|
|
let config = AdaptivePoolConfig {
|
|
evaluation_interval: Duration::from_millis(100), // Fast evaluation for testing
|
|
min_pool_capacity: 5,
|
|
max_pool_capacity: 30,
|
|
..AdaptivePoolConfig::default()
|
|
};
|
|
|
|
let manager = AdaptivePoolManager::new(config, hierarchical_pool.clone());
|
|
|
|
println!(" 📊 Starting stress test configuration:");
|
|
println!(" Pool sizes: 64KB, 256KB, 900KB, 2MB");
|
|
println!(" Load duration: 2 seconds");
|
|
println!(" Frame rate: ~100 FPS");
|
|
|
|
// Start manager in background (with timeout for testing)
|
|
let manager_handle = tokio::spawn(async move {
|
|
// Run adaptive management for limited time in test
|
|
timeout(Duration::from_secs(2), async {
|
|
manager.start_adaptive_management().await;
|
|
}).await
|
|
});
|
|
|
|
// Generate high load for different frame sizes
|
|
let memory_monitor_clone = memory_monitor.clone();
|
|
let load_handle = tokio::spawn(async move {
|
|
let frame_sizes = [64 * 1024, 256 * 1024, 900 * 1024, 2 * 1024 * 1024];
|
|
|
|
for i in 0..200 {
|
|
let frame_size = frame_sizes[i % frame_sizes.len()];
|
|
memory_monitor_clone.record_frame_processed(frame_size, 4); // 4 subscribers
|
|
|
|
if i % 30 == 0 {
|
|
sleep(Duration::from_millis(10)).await;
|
|
}
|
|
}
|
|
});
|
|
|
|
// Wait for both load generation and manager
|
|
let (_manager_result, _load_result) = tokio::join!(manager_handle, load_handle);
|
|
|
|
// Check final pool state
|
|
let final_stats = hierarchical_pool.all_stats();
|
|
let total_memory = hierarchical_pool.total_memory_usage();
|
|
|
|
println!(" 📈 Stress test results:");
|
|
println!(" Pool configurations: {} different sizes", final_stats.len());
|
|
println!(" Total pool memory: {} KB", total_memory / 1024);
|
|
|
|
for (size, stats) in final_stats.iter().take(4) {
|
|
println!(" {}KB pool: {} allocations, {:.1}% hit rate",
|
|
size / 1024, stats.total_allocations, stats.cache_hit_rate * 100.0);
|
|
}
|
|
|
|
let global_stats = memory_monitor.stats();
|
|
println!(" Global frames processed: {}", global_stats.frames_processed);
|
|
println!(" Global memory saved: {:.1} MB", global_stats.bytes_saved_total as f64 / 1_000_000.0);
|
|
|
|
assert!(global_stats.frames_processed > 0, "Should have processed frames");
|
|
println!(" ✅ Adaptive management stress test completed");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Test memory optimization integration
|
|
pub async fn test_memory_optimization_integration() -> anyhow::Result<()> {
|
|
println!("\n📈 Memory Optimization Integration Test");
|
|
|
|
let memory_monitor = Arc::new(MemoryMonitor::new());
|
|
let hierarchical_pool = Arc::new(HierarchicalFramePool::new(10));
|
|
|
|
// Generate some usage patterns
|
|
for frame_count in 0..100 {
|
|
let frame_size = match frame_count % 4 {
|
|
0 => 64 * 1024, // 64KB
|
|
1 => 256 * 1024, // 256KB
|
|
2 => 900 * 1024, // 900KB
|
|
_ => 2 * 1024 * 1024, // 2MB
|
|
};
|
|
|
|
memory_monitor.record_frame_processed(frame_size, 3);
|
|
|
|
// Get buffer from pool to simulate usage
|
|
if frame_count % 10 == 0 {
|
|
let _buffer = hierarchical_pool.acquire(frame_size);
|
|
// Buffer automatically returns to pool on drop
|
|
}
|
|
}
|
|
|
|
// Check optimization results
|
|
let memory_stats = memory_monitor.stats();
|
|
let pool_stats = hierarchical_pool.all_stats();
|
|
|
|
println!(" 📊 Integration results:");
|
|
println!(" Frames processed: {}", memory_stats.frames_processed);
|
|
println!(" Memory saved: {:.2} MB", memory_stats.bytes_saved_total as f64 / 1_000_000.0);
|
|
println!(" Pool configurations: {}", pool_stats.len());
|
|
|
|
// Verify optimization is working
|
|
assert!(memory_stats.bytes_saved_total > 0, "Should have saved memory");
|
|
assert!(memory_stats.frames_processed == 100, "Should have processed all frames");
|
|
|
|
// Check pool efficiency
|
|
for (size, stats) in pool_stats {
|
|
if stats.total_allocations > 0 {
|
|
println!(" {}KB pool efficiency: {:.1}% hit rate",
|
|
size / 1024, stats.cache_hit_rate * 100.0);
|
|
}
|
|
}
|
|
|
|
println!(" ✅ Memory optimization integration verified");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[tokio::test]
|
|
async fn test_integration_suite() {
|
|
test_adaptive_pool_integration().await.unwrap();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_stress_test() {
|
|
stress_test_adaptive_managers().await.unwrap();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_memory_optimization() {
|
|
test_memory_optimization_integration().await.unwrap();
|
|
}
|
|
} |