1144 lines
42 KiB
Rust
1144 lines
42 KiB
Rust
//! 综合性能和压力测试框架
|
||
//!
|
||
//! 本模块提供全面的性能和压力测试,包括:
|
||
//! - 跨架构翻译性能测试
|
||
//! - JIT编译性能压力测试
|
||
//! - 内存管理压力测试
|
||
//! - 并发执行压力测试
|
||
//! - 资源泄漏检测
|
||
//! - 长时间运行稳定性测试
|
||
|
||
use std::collections::HashMap;
|
||
use std::sync::{Arc, Barrier, Mutex};
|
||
use std::time::{Duration, Instant};
|
||
use std::thread;
|
||
use std::sync::atomic::{AtomicU64, AtomicBool, Ordering};
|
||
|
||
use vm_cross_arch::{UnifiedExecutor, CrossArchTranslator};
|
||
use vm_core::{GuestArch, MMU};
|
||
use vm_engine_jit::core::{JITEngine, JITConfig};
|
||
use vm_mem::{SoftMmu, MemoryManager, NUMAAllocator};
|
||
use vm_ir::{IRBlock, IRBuilder, IROp, Terminator, MemFlags};
|
||
|
||
/// 性能测试结果
|
||
#[derive(Debug, Clone)]
|
||
pub struct PerformanceTestResult {
|
||
/// 测试名称
|
||
pub name: String,
|
||
/// 执行时间(毫秒)
|
||
pub execution_time_ms: u64,
|
||
/// 内存使用量(字节)
|
||
pub memory_usage_bytes: u64,
|
||
/// 操作数
|
||
pub operations: u64,
|
||
/// 错误数
|
||
pub errors: u64,
|
||
/// 吞吐量(操作/秒)
|
||
pub throughput_ops_per_sec: f64,
|
||
}
|
||
|
||
/// 压力测试配置
|
||
#[derive(Debug, Clone)]
|
||
pub struct StressTestConfig {
|
||
/// 测试持续时间(秒)
|
||
pub duration_seconds: u64,
|
||
/// 并发线程数
|
||
pub thread_count: u32,
|
||
/// 操作间隔(微秒)
|
||
pub operation_interval_us: Option<u64>,
|
||
/// 内存压力级别(1-10)
|
||
pub memory_pressure_level: u8,
|
||
/// CPU压力级别(1-10)
|
||
pub cpu_pressure_level: u8,
|
||
}
|
||
|
||
impl Default for StressTestConfig {
|
||
fn default() -> Self {
|
||
Self {
|
||
duration_seconds: 60, // 默认1分钟
|
||
thread_count: 4,
|
||
operation_interval_us: None,
|
||
memory_pressure_level: 5,
|
||
cpu_pressure_level: 5,
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 综合性能和压力测试框架
|
||
pub struct PerformanceStressTestFramework {
|
||
/// 测试结果
|
||
results: Arc<Mutex<Vec<PerformanceTestResult>>>,
|
||
/// 是否正在运行
|
||
running: Arc<AtomicBool>,
|
||
/// 开始时间
|
||
start_time: Arc<Mutex<Option<Instant>>>,
|
||
}
|
||
|
||
impl PerformanceStressTestFramework {
|
||
/// 创建新的测试框架
|
||
pub fn new() -> Self {
|
||
Self {
|
||
results: Arc::new(Mutex::new(Vec::new())),
|
||
running: Arc::new(AtomicBool::new(false)),
|
||
start_time: Arc::new(Mutex::new(None)),
|
||
}
|
||
}
|
||
|
||
/// 运行跨架构翻译性能测试
|
||
pub fn run_cross_arch_performance_test(&mut self) -> PerformanceTestResult {
|
||
let test_name = "cross_arch_translation".to_string();
|
||
let start_time = Instant::now();
|
||
let mut operations = 0;
|
||
let mut errors = 0;
|
||
|
||
// 测试不同架构组合的翻译性能
|
||
let arch_combinations = vec![
|
||
(GuestArch::X86_64, GuestArch::ARM64),
|
||
(GuestArch::X86_64, GuestArch::RISCV64),
|
||
(GuestArch::ARM64, GuestArch::X86_64),
|
||
(GuestArch::ARM64, GuestArch::RISCV64),
|
||
(GuestArch::RISCV64, GuestArch::X86_64),
|
||
(GuestArch::RISCV64, GuestArch::ARM64),
|
||
];
|
||
|
||
for (src_arch, dst_arch) in arch_combinations {
|
||
// 创建执行器
|
||
let mut executor = match UnifiedExecutor::auto_create(src_arch, 128 * 1024 * 1024) {
|
||
Ok(exec) => exec,
|
||
Err(_) => {
|
||
errors += 1;
|
||
continue;
|
||
}
|
||
};
|
||
|
||
// 创建测试代码
|
||
let test_code = self.create_test_code(src_arch);
|
||
let code_base = 0x1000;
|
||
|
||
// 加载代码
|
||
for (i, byte) in test_code.iter().enumerate() {
|
||
if let Err(_) = executor.mmu_mut().write(code_base + i as u64, *byte as u64, 1) {
|
||
errors += 1;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// 执行翻译测试
|
||
for _ in 0..100 {
|
||
match executor.execute(code_base) {
|
||
Ok(_) => operations += 1,
|
||
Err(_) => errors += 1,
|
||
}
|
||
}
|
||
}
|
||
|
||
let execution_time = start_time.elapsed();
|
||
let memory_usage = self.estimate_memory_usage();
|
||
|
||
let result = PerformanceTestResult {
|
||
name: test_name,
|
||
execution_time_ms: execution_time.as_millis() as u64,
|
||
memory_usage_bytes: memory_usage,
|
||
operations,
|
||
errors,
|
||
throughput_ops_per_sec: operations as f64 / execution_time.as_secs_f64(),
|
||
};
|
||
|
||
self.results.lock().unwrap().push(result.clone());
|
||
result
|
||
}
|
||
|
||
/// 运行JIT编译性能压力测试
|
||
pub fn run_jit_compilation_stress_test(&mut self, config: StressTestConfig) -> PerformanceTestResult {
|
||
let test_name = "jit_compilation_stress".to_string();
|
||
let running = Arc::new(AtomicBool::new(true));
|
||
let operations = Arc::new(AtomicU64::new(0));
|
||
let errors = Arc::new(AtomicU64::new(0));
|
||
let barrier = Arc::new(Barrier::new(config.thread_count as usize));
|
||
|
||
let start_time = Instant::now();
|
||
let mut handles = Vec::new();
|
||
|
||
for thread_id in 0..config.thread_count {
|
||
let running_clone = running.clone();
|
||
let operations_clone = operations.clone();
|
||
let errors_clone = errors.clone();
|
||
let barrier_clone = barrier.clone();
|
||
let memory_pressure = config.memory_pressure_level;
|
||
let cpu_pressure = config.cpu_pressure_level;
|
||
|
||
let handle = thread::spawn(move || {
|
||
// 等待所有线程就绪
|
||
barrier_clone.wait();
|
||
|
||
// 创建JIT引擎
|
||
let mut jit = JITEngine::new(JITConfig::default());
|
||
|
||
// 根据压力级别调整工作负载
|
||
let block_count = match memory_pressure {
|
||
1..=3 => 10,
|
||
4..=6 => 50,
|
||
7..=8 => 100,
|
||
9..=10 => 200,
|
||
_ => 50,
|
||
};
|
||
|
||
let complexity = match cpu_pressure {
|
||
1..=3 => 100,
|
||
4..=6 => 500,
|
||
7..=8 => 1000,
|
||
9..=10 => 2000,
|
||
_ => 500,
|
||
};
|
||
|
||
while running_clone.load(Ordering::Relaxed) {
|
||
// 创建测试IR块
|
||
let block = create_complex_ir_block(0x1000 + thread_id as u64 * 0x10000, complexity);
|
||
|
||
// 编译块
|
||
match jit.compile(&block) {
|
||
Ok(_) => operations_clone.fetch_add(1, Ordering::Relaxed),
|
||
Err(_) => errors_clone.fetch_add(1, Ordering::Relaxed),
|
||
};
|
||
|
||
// 根据配置添加延迟
|
||
if let Some(interval) = config.operation_interval_us {
|
||
thread::sleep(Duration::from_micros(interval));
|
||
}
|
||
|
||
// 创建多个块以增加内存压力
|
||
for i in 0..block_count {
|
||
let addr = 0x2000 + thread_id as u64 * 0x10000 + i as u64 * 0x1000;
|
||
let block = create_basic_ir_block(addr, 100);
|
||
let _ = jit.compile(&block);
|
||
}
|
||
}
|
||
});
|
||
|
||
handles.push(handle);
|
||
}
|
||
|
||
// 运行指定时间
|
||
thread::sleep(Duration::from_secs(config.duration_seconds));
|
||
running.store(false, Ordering::Relaxed);
|
||
|
||
// 等待所有线程完成
|
||
for handle in handles {
|
||
let _ = handle.join();
|
||
}
|
||
|
||
let execution_time = start_time.elapsed();
|
||
let total_operations = operations.load(Ordering::Relaxed);
|
||
let total_errors = errors.load(Ordering::Relaxed);
|
||
let memory_usage = self.estimate_memory_usage();
|
||
|
||
let result = PerformanceTestResult {
|
||
name: test_name,
|
||
execution_time_ms: execution_time.as_millis() as u64,
|
||
memory_usage_bytes: memory_usage,
|
||
operations: total_operations,
|
||
errors: total_errors,
|
||
throughput_ops_per_sec: total_operations as f64 / execution_time.as_secs_f64(),
|
||
};
|
||
|
||
self.results.lock().unwrap().push(result.clone());
|
||
result
|
||
}
|
||
|
||
/// 运行内存管理压力测试
|
||
pub fn run_memory_stress_test(&mut self, config: StressTestConfig) -> PerformanceTestResult {
|
||
let test_name = "memory_management_stress".to_string();
|
||
let running = Arc::new(AtomicBool::new(true));
|
||
let operations = Arc::new(AtomicU64::new(0));
|
||
let errors = Arc::new(AtomicU64::new(0));
|
||
let barrier = Arc::new(Barrier::new(config.thread_count as usize));
|
||
|
||
let start_time = Instant::now();
|
||
let mut handles = Vec::new();
|
||
|
||
for thread_id in 0..config.thread_count {
|
||
let running_clone = running.clone();
|
||
let operations_clone = operations.clone();
|
||
let errors_clone = errors.clone();
|
||
let barrier_clone = barrier.clone();
|
||
let memory_pressure = config.memory_pressure_level;
|
||
|
||
let handle = thread::spawn(move || {
|
||
barrier_clone.wait();
|
||
|
||
// 创建内存管理器
|
||
let mut memory_manager = MemoryManager::new(1024 * 1024 * 1024); // 1GB
|
||
let mut mmu = SoftMmu::new(1024 * 1024 * 1024, false);
|
||
|
||
// 根据压力级别调整内存操作大小
|
||
let allocation_size = match memory_pressure {
|
||
1..=3 => 1024, // 1KB
|
||
4..=6 => 10240, // 10KB
|
||
7..=8 => 102400, // 100KB
|
||
9..=10 => 1024000, // 1MB
|
||
_ => 10240,
|
||
};
|
||
|
||
let allocation_count = match memory_pressure {
|
||
1..=3 => 100,
|
||
4..=6 => 500,
|
||
7..=8 => 1000,
|
||
9..=10 => 2000,
|
||
_ => 500,
|
||
};
|
||
|
||
let mut allocations = Vec::new();
|
||
|
||
while running_clone.load(Ordering::Relaxed) {
|
||
// 分配内存
|
||
for i in 0..allocation_count {
|
||
let addr = thread_id as u64 * 0x10000000 + i as u64 * allocation_size;
|
||
match memory_manager.allocate(addr, allocation_size) {
|
||
Ok(_) => {
|
||
allocations.push(addr);
|
||
operations_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
Err(_) => errors_clone.fetch_add(1, Ordering::Relaxed),
|
||
}
|
||
}
|
||
|
||
// 执行内存读写操作
|
||
for &addr in &allocations {
|
||
for offset in (0..allocation_size).step_by(4096) {
|
||
// 写入
|
||
if let Err(_) = mmu.write(addr + offset as u64, 0xDEADBEEF, 8) {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
} else {
|
||
operations_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
|
||
// 读取
|
||
if let Err(_) = mmu.read(addr + offset as u64, 8) {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
} else {
|
||
operations_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 释放部分内存
|
||
for _ in 0..allocation_count / 2 {
|
||
if let Some(addr) = allocations.pop() {
|
||
if let Err(_) = memory_manager.deallocate(addr) {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
} else {
|
||
operations_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 根据配置添加延迟
|
||
if let Some(interval) = config.operation_interval_us {
|
||
thread::sleep(Duration::from_micros(interval));
|
||
}
|
||
}
|
||
});
|
||
|
||
handles.push(handle);
|
||
}
|
||
|
||
// 运行指定时间
|
||
thread::sleep(Duration::from_secs(config.duration_seconds));
|
||
running.store(false, Ordering::Relaxed);
|
||
|
||
// 等待所有线程完成
|
||
for handle in handles {
|
||
let _ = handle.join();
|
||
}
|
||
|
||
let execution_time = start_time.elapsed();
|
||
let total_operations = operations.load(Ordering::Relaxed);
|
||
let total_errors = errors.load(Ordering::Relaxed);
|
||
let memory_usage = self.estimate_memory_usage();
|
||
|
||
let result = PerformanceTestResult {
|
||
name: test_name,
|
||
execution_time_ms: execution_time.as_millis() as u64,
|
||
memory_usage_bytes: memory_usage,
|
||
operations: total_operations,
|
||
errors: total_errors,
|
||
throughput_ops_per_sec: total_operations as f64 / execution_time.as_secs_f64(),
|
||
};
|
||
|
||
self.results.lock().unwrap().push(result.clone());
|
||
result
|
||
}
|
||
|
||
/// 运行并发执行压力测试
|
||
pub fn run_concurrent_execution_stress_test(&mut self, config: StressTestConfig) -> PerformanceTestResult {
|
||
let test_name = "concurrent_execution_stress".to_string();
|
||
let running = Arc::new(AtomicBool::new(true));
|
||
let operations = Arc::new(AtomicU64::new(0));
|
||
let errors = Arc::new(AtomicU64::new(0));
|
||
let barrier = Arc::new(Barrier::new(config.thread_count as usize));
|
||
|
||
let start_time = Instant::now();
|
||
let mut handles = Vec::new();
|
||
|
||
for thread_id in 0..config.thread_count {
|
||
let running_clone = running.clone();
|
||
let operations_clone = operations.clone();
|
||
let errors_clone = errors.clone();
|
||
let barrier_clone = barrier.clone();
|
||
let cpu_pressure = config.cpu_pressure_level;
|
||
|
||
let handle = thread::spawn(move || {
|
||
barrier_clone.wait();
|
||
|
||
// 创建执行器
|
||
let mut executor = match UnifiedExecutor::auto_create(GuestArch::X86_64, 128 * 1024 * 1024) {
|
||
Ok(exec) => exec,
|
||
Err(_) => {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
return;
|
||
}
|
||
};
|
||
|
||
// 根据CPU压力级别调整工作负载
|
||
let execution_count = match cpu_pressure {
|
||
1..=3 => 10,
|
||
4..=6 => 50,
|
||
7..=8 => 100,
|
||
9..=10 => 200,
|
||
_ => 50,
|
||
};
|
||
|
||
let code_complexity = match cpu_pressure {
|
||
1..=3 => 10,
|
||
4..=6 => 50,
|
||
7..=8 => 100,
|
||
9..=10 => 200,
|
||
_ => 50,
|
||
};
|
||
|
||
// 创建测试代码
|
||
let test_code = create_complex_test_code(code_complexity);
|
||
let code_base = 0x1000 + thread_id as u64 * 0x10000;
|
||
|
||
// 加载代码
|
||
for (i, byte) in test_code.iter().enumerate() {
|
||
if let Err(_) = executor.mmu_mut().write(code_base + i as u64, *byte as u64, 1) {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
}
|
||
|
||
while running_clone.load(Ordering::Relaxed) {
|
||
// 执行代码多次
|
||
for _ in 0..execution_count {
|
||
match executor.execute(code_base) {
|
||
Ok(_) => operations_clone.fetch_add(1, Ordering::Relaxed),
|
||
Err(_) => errors_clone.fetch_add(1, Ordering::Relaxed),
|
||
};
|
||
}
|
||
|
||
// 根据配置添加延迟
|
||
if let Some(interval) = config.operation_interval_us {
|
||
thread::sleep(Duration::from_micros(interval));
|
||
}
|
||
}
|
||
});
|
||
|
||
handles.push(handle);
|
||
}
|
||
|
||
// 运行指定时间
|
||
thread::sleep(Duration::from_secs(config.duration_seconds));
|
||
running.store(false, Ordering::Relaxed);
|
||
|
||
// 等待所有线程完成
|
||
for handle in handles {
|
||
let _ = handle.join();
|
||
}
|
||
|
||
let execution_time = start_time.elapsed();
|
||
let total_operations = operations.load(Ordering::Relaxed);
|
||
let total_errors = errors.load(Ordering::Relaxed);
|
||
let memory_usage = self.estimate_memory_usage();
|
||
|
||
let result = PerformanceTestResult {
|
||
name: test_name,
|
||
execution_time_ms: execution_time.as_millis() as u64,
|
||
memory_usage_bytes: memory_usage,
|
||
operations: total_operations,
|
||
errors: total_errors,
|
||
throughput_ops_per_sec: total_operations as f64 / execution_time.as_secs_f64(),
|
||
};
|
||
|
||
self.results.lock().unwrap().push(result.clone());
|
||
result
|
||
}
|
||
|
||
/// 运行资源泄漏检测测试
|
||
pub fn run_resource_leak_test(&mut self) -> PerformanceTestResult {
|
||
let test_name = "resource_leak_detection".to_string();
|
||
let start_time = Instant::now();
|
||
let mut operations = 0;
|
||
let mut errors = 0;
|
||
|
||
// 记录初始资源使用
|
||
let initial_memory = self.estimate_memory_usage();
|
||
|
||
// 创建和销毁大量资源
|
||
for _ in 0..1000 {
|
||
// 创建JIT引擎
|
||
let mut jit = JITEngine::new(JITConfig::default());
|
||
|
||
// 创建并编译多个块
|
||
for i in 0..10 {
|
||
let block = create_basic_ir_block(0x1000 + i as u64 * 0x1000, 100);
|
||
if let Ok(_) = jit.compile(&block) {
|
||
operations += 1;
|
||
} else {
|
||
errors += 1;
|
||
}
|
||
}
|
||
|
||
// 创建执行器
|
||
if let Ok(mut executor) = UnifiedExecutor::auto_create(GuestArch::X86_64, 128 * 1024 * 1024) {
|
||
// 创建测试代码
|
||
let test_code = self.create_test_code(GuestArch::X86_64);
|
||
let code_base = 0x1000;
|
||
|
||
// 加载代码
|
||
for (i, byte) in test_code.iter().enumerate() {
|
||
if let Err(_) = executor.mmu_mut().write(code_base + i as u64, *byte as u64, 1) {
|
||
errors += 1;
|
||
}
|
||
}
|
||
|
||
// 执行代码
|
||
for _ in 0..10 {
|
||
match executor.execute(code_base) {
|
||
Ok(_) => operations += 1,
|
||
Err(_) => errors += 1,
|
||
}
|
||
}
|
||
} else {
|
||
errors += 1;
|
||
}
|
||
|
||
// 创建内存管理器
|
||
let mut memory_manager = MemoryManager::new(1024 * 1024); // 1MB
|
||
let mut mmu = SoftMmu::new(1024 * 1024, false);
|
||
|
||
// 分配和释放内存
|
||
for i in 0..100 {
|
||
let addr = i as u64 * 4096;
|
||
if let Ok(_) = memory_manager.allocate(addr, 4096) {
|
||
operations += 1;
|
||
|
||
// 执行内存操作
|
||
if let Ok(_) = mmu.write(addr, 0xDEADBEEF, 8) {
|
||
operations += 1;
|
||
} else {
|
||
errors += 1;
|
||
}
|
||
|
||
if let Ok(_) = mmu.read(addr, 8) {
|
||
operations += 1;
|
||
} else {
|
||
errors += 1;
|
||
}
|
||
|
||
if let Ok(_) = memory_manager.deallocate(addr) {
|
||
operations += 1;
|
||
} else {
|
||
errors += 1;
|
||
}
|
||
} else {
|
||
errors += 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 强制垃圾回收
|
||
// 这里应该调用实际的GC方法,但由于我们不知道具体的API,我们只是等待一下
|
||
thread::sleep(Duration::from_millis(100));
|
||
|
||
// 记录最终资源使用
|
||
let final_memory = self.estimate_memory_usage();
|
||
let memory_leak = final_memory.saturating_sub(initial_memory);
|
||
|
||
let execution_time = start_time.elapsed();
|
||
|
||
let result = PerformanceTestResult {
|
||
name: test_name,
|
||
execution_time_ms: execution_time.as_millis() as u64,
|
||
memory_usage_bytes: memory_leak,
|
||
operations,
|
||
errors,
|
||
throughput_ops_per_sec: operations as f64 / execution_time.as_secs_f64(),
|
||
};
|
||
|
||
self.results.lock().unwrap().push(result.clone());
|
||
result
|
||
}
|
||
|
||
/// 运行长时间稳定性测试
|
||
pub fn run_long_term_stability_test(&mut self, duration_hours: u64) -> PerformanceTestResult {
|
||
let test_name = "long_term_stability".to_string();
|
||
let running = Arc::new(AtomicBool::new(true));
|
||
let operations = Arc::new(AtomicU64::new(0));
|
||
let errors = Arc::new(AtomicU64::new(0));
|
||
let start_time = Instant::now();
|
||
|
||
let mut handles = Vec::new();
|
||
|
||
// 创建多个线程执行不同类型的任务
|
||
for thread_id in 0..4 {
|
||
let running_clone = running.clone();
|
||
let operations_clone = operations.clone();
|
||
let errors_clone = errors.clone();
|
||
|
||
let handle = thread::spawn(move || {
|
||
while running_clone.load(Ordering::Relaxed) {
|
||
match thread_id {
|
||
0 => {
|
||
// JIT编译任务
|
||
let mut jit = JITEngine::new(JITConfig::default());
|
||
let block = create_random_ir_block(0x1000 + thread_id as u64 * 0x10000);
|
||
if let Ok(_) = jit.compile(&block) {
|
||
operations_clone.fetch_add(1, Ordering::Relaxed);
|
||
} else {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
}
|
||
1 => {
|
||
// 跨架构翻译任务
|
||
if let Ok(mut executor) = UnifiedExecutor::auto_create(GuestArch::X86_64, 128 * 1024 * 1024) {
|
||
let test_code = create_test_code_x86();
|
||
let code_base = 0x1000;
|
||
|
||
for (i, byte) in test_code.iter().enumerate() {
|
||
if let Err(_) = executor.mmu_mut().write(code_base + i as u64, *byte as u64, 1) {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
}
|
||
|
||
if let Ok(_) = executor.execute(code_base) {
|
||
operations_clone.fetch_add(1, Ordering::Relaxed);
|
||
} else {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
} else {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
}
|
||
2 => {
|
||
// 内存管理任务
|
||
let mut memory_manager = MemoryManager::new(1024 * 1024); // 1MB
|
||
let mut mmu = SoftMmu::new(1024 * 1024, false);
|
||
|
||
for i in 0..10 {
|
||
let addr = i as u64 * 4096;
|
||
if let Ok(_) = memory_manager.allocate(addr, 4096) {
|
||
if let Ok(_) = mmu.write(addr, 0xDEADBEEF, 8) {
|
||
if let Ok(_) = mmu.read(addr, 8) {
|
||
operations_clone.fetch_add(3, Ordering::Relaxed);
|
||
} else {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
} else {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
|
||
if let Ok(_) = memory_manager.deallocate(addr) {
|
||
operations_clone.fetch_add(1, Ordering::Relaxed);
|
||
} else {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
} else {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
}
|
||
}
|
||
3 => {
|
||
// 混合任务
|
||
let mut jit = JITEngine::new(JITConfig::default());
|
||
let block = create_basic_ir_block(0x1000 + thread_id as u64 * 0x10000, 100);
|
||
|
||
if let Ok(_) = jit.compile(&block) {
|
||
operations_clone.fetch_add(1, Ordering::Relaxed);
|
||
} else {
|
||
errors_clone.fetch_add(1, Ordering::Relaxed);
|
||
}
|
||
|
||
thread::sleep(Duration::from_millis(10));
|
||
}
|
||
_ => {}
|
||
}
|
||
|
||
// 短暂休息
|
||
thread::sleep(Duration::from_millis(10));
|
||
}
|
||
});
|
||
|
||
handles.push(handle);
|
||
}
|
||
|
||
// 运行指定时间
|
||
thread::sleep(Duration::from_secs(duration_hours * 3600));
|
||
running.store(false, Ordering::Relaxed);
|
||
|
||
// 等待所有线程完成
|
||
for handle in handles {
|
||
let _ = handle.join();
|
||
}
|
||
|
||
let execution_time = start_time.elapsed();
|
||
let total_operations = operations.load(Ordering::Relaxed);
|
||
let total_errors = errors.load(Ordering::Relaxed);
|
||
let memory_usage = self.estimate_memory_usage();
|
||
|
||
let result = PerformanceTestResult {
|
||
name: test_name,
|
||
execution_time_ms: execution_time.as_millis() as u64,
|
||
memory_usage_bytes: memory_usage,
|
||
operations: total_operations,
|
||
errors: total_errors,
|
||
throughput_ops_per_sec: total_operations as f64 / execution_time.as_secs_f64(),
|
||
};
|
||
|
||
self.results.lock().unwrap().push(result.clone());
|
||
result
|
||
}
|
||
|
||
/// 获取所有测试结果
|
||
pub fn get_results(&self) -> Vec<PerformanceTestResult> {
|
||
self.results.lock().unwrap().clone()
|
||
}
|
||
|
||
/// 打印测试结果
|
||
pub fn print_results(&self) {
|
||
let results = self.results.lock().unwrap();
|
||
|
||
println!("\n==== Performance and Stress Test Results ====");
|
||
println!("{:<30} {:<15} {:<15} {:<10} {:<10} {:<15}",
|
||
"Test Name", "Time (ms)", "Memory (MB)", "Ops", "Errors", "Throughput");
|
||
println!("{}", "=".repeat(100));
|
||
|
||
for result in results.iter() {
|
||
println!("{:<30} {:<15} {:<15.2} {:<10} {:<10} {:<15.0}",
|
||
result.name,
|
||
result.execution_time_ms,
|
||
result.memory_usage_bytes as f64 / 1024.0 / 1024.0,
|
||
result.operations,
|
||
result.errors,
|
||
result.throughput_ops_per_sec);
|
||
}
|
||
}
|
||
|
||
/// 生成测试报告
|
||
pub fn generate_report(&self) -> String {
|
||
let results = self.results.lock().unwrap();
|
||
let mut report = String::new();
|
||
|
||
report.push_str("# Performance and Stress Test Report\n\n");
|
||
|
||
for result in results.iter() {
|
||
report.push_str(&format!("## {}\n", result.name));
|
||
report.push_str(&format!("- Execution Time: {} ms\n", result.execution_time_ms));
|
||
report.push_str(&format!("- Memory Usage: {:.2} MB\n", result.memory_usage_bytes as f64 / 1024.0 / 1024.0));
|
||
report.push_str(&format!("- Operations: {}\n", result.operations));
|
||
report.push_str(&format!("- Errors: {}\n", result.errors));
|
||
report.push_str(&format!("- Throughput: {:.0} ops/sec\n\n", result.throughput_ops_per_sec));
|
||
}
|
||
|
||
report
|
||
}
|
||
|
||
/// 估算内存使用量
|
||
fn estimate_memory_usage(&self) -> u64 {
|
||
// 这里应该使用实际的内存监控API
|
||
// 为了示例,我们返回一个模拟值
|
||
use std::sync::atomic::{AtomicU64, Ordering};
|
||
static MEMORY_COUNTER: AtomicU64 = AtomicU64::new(0);
|
||
MEMORY_COUNTER.fetch_add(1024 * 1024, Ordering::Relaxed) // 模拟1MB增长
|
||
}
|
||
|
||
/// 创建测试代码
|
||
fn create_test_code(&self, arch: GuestArch) -> Vec<u8> {
|
||
match arch {
|
||
GuestArch::X86_64 => create_test_code_x86(),
|
||
GuestArch::ARM64 => create_test_code_arm(),
|
||
GuestArch::RISCV64 => create_test_code_riscv(),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 创建基础IR块
|
||
fn create_basic_ir_block(addr: u64, instruction_count: usize) -> IRBlock {
|
||
let mut builder = IRBuilder::new(addr);
|
||
|
||
for i in 0..instruction_count {
|
||
builder.push(IROp::MovImm { dst: (i % 16) as u32, imm: (i * 42) as u64 });
|
||
builder.push(IROp::Add {
|
||
dst: 0,
|
||
src1: 0,
|
||
src2: (i % 16) as u32,
|
||
});
|
||
}
|
||
|
||
builder.set_term(Terminator::Ret);
|
||
builder.build()
|
||
}
|
||
|
||
/// 创建复杂IR块
|
||
fn create_complex_ir_block(addr: u64, complexity: usize) -> IRBlock {
|
||
let mut builder = IRBuilder::new(addr);
|
||
|
||
for i in 0..complexity {
|
||
match i % 8 {
|
||
0 => {
|
||
builder.push(IROp::MovImm { dst: 1, imm: i as u64 });
|
||
builder.push(IROp::Add {
|
||
dst: 0,
|
||
src1: 0,
|
||
src2: 1,
|
||
});
|
||
}
|
||
1 => {
|
||
builder.push(IROp::Sub {
|
||
dst: 2,
|
||
src1: 0,
|
||
src2: 1,
|
||
});
|
||
}
|
||
2 => {
|
||
builder.push(IROp::Mul {
|
||
dst: 3,
|
||
src1: 2,
|
||
src2: 1,
|
||
});
|
||
}
|
||
3 => {
|
||
builder.push(IROp::Div {
|
||
dst: 4,
|
||
src1: 3,
|
||
src2: 1,
|
||
signed: false,
|
||
});
|
||
}
|
||
4 => {
|
||
builder.push(IROp::Load {
|
||
dst: 5,
|
||
base: 0,
|
||
offset: (i * 8) as i64,
|
||
size: 8,
|
||
flags: MemFlags::default(),
|
||
});
|
||
}
|
||
5 => {
|
||
builder.push(IROp::Store {
|
||
base: 0,
|
||
offset: (i * 8) as i64,
|
||
size: 8,
|
||
src: 5,
|
||
flags: MemFlags::default(),
|
||
});
|
||
}
|
||
6 => {
|
||
builder.push(IROp::ShiftLeft {
|
||
dst: 6,
|
||
src: 0,
|
||
amount: 2,
|
||
});
|
||
}
|
||
_ => {
|
||
builder.push(IROp::ShiftRight {
|
||
dst: 7,
|
||
src: 6,
|
||
amount: 1,
|
||
signed: false,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
builder.set_term(Terminator::Ret);
|
||
builder.build()
|
||
}
|
||
|
||
/// 创建随机IR块
|
||
fn create_random_ir_block(addr: u64) -> IRBlock {
|
||
use std::collections::hash_map::DefaultHasher;
|
||
use std::hash::{Hash, Hasher};
|
||
|
||
let mut hasher = DefaultHasher::new();
|
||
addr.hash(&mut hasher);
|
||
let seed = hasher.finish();
|
||
|
||
let mut builder = IRBuilder::new(addr);
|
||
let instruction_count = (seed % 100) as usize + 10;
|
||
|
||
for i in 0..instruction_count {
|
||
let op_type = (seed + i as u64) % 8;
|
||
match op_type {
|
||
0 => {
|
||
builder.push(IROp::MovImm { dst: (i % 16) as u32, imm: seed + i as u64 });
|
||
}
|
||
1 => {
|
||
builder.push(IROp::Add {
|
||
dst: 0,
|
||
src1: (i % 16) as u32,
|
||
src2: ((i + 1) % 16) as u32,
|
||
});
|
||
}
|
||
2 => {
|
||
builder.push(IROp::Sub {
|
||
dst: 1,
|
||
src1: (i % 16) as u32,
|
||
src2: ((i + 1) % 16) as u32,
|
||
});
|
||
}
|
||
3 => {
|
||
builder.push(IROp::Mul {
|
||
dst: 2,
|
||
src1: (i % 16) as u32,
|
||
src2: ((i + 1) % 16) as u32,
|
||
});
|
||
}
|
||
4 => {
|
||
builder.push(IROp::Load {
|
||
dst: (i % 16) as u32,
|
||
base: 0,
|
||
offset: (i * 8) as i64,
|
||
size: 8,
|
||
flags: MemFlags::default(),
|
||
});
|
||
}
|
||
5 => {
|
||
builder.push(IROp::Store {
|
||
base: 0,
|
||
offset: (i * 8) as i64,
|
||
size: 8,
|
||
src: (i % 16) as u32,
|
||
flags: MemFlags::default(),
|
||
});
|
||
}
|
||
6 => {
|
||
builder.push(IROp::ShiftLeft {
|
||
dst: (i % 16) as u32,
|
||
src: (i % 16) as u32,
|
||
amount: (i % 8) as u8,
|
||
});
|
||
}
|
||
_ => {
|
||
builder.push(IROp::ShiftRight {
|
||
dst: (i % 16) as u32,
|
||
src: (i % 16) as u32,
|
||
amount: (i % 8) as u8,
|
||
signed: false,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
builder.set_term(Terminator::Ret);
|
||
builder.build()
|
||
}
|
||
|
||
/// 创建x86测试代码
|
||
fn create_test_code_x86() -> Vec<u8> {
|
||
vec![
|
||
0xB8, 0x0A, 0x00, 0x00, 0x00, // mov eax, 10
|
||
0xBB, 0x14, 0x00, 0x00, 0x00, // mov ebx, 20
|
||
0x01, 0xD8, // add eax, ebx
|
||
0x83, 0xC0, 0x05, // add eax, 5
|
||
0x29, 0xD8, // sub eax, ebx
|
||
0xC3, // ret
|
||
]
|
||
}
|
||
|
||
/// 创建ARM测试代码
|
||
fn create_test_code_arm() -> Vec<u8> {
|
||
vec![
|
||
0x10, 0x00, 0x80, 0x52, // mov w16, #10
|
||
0x14, 0x00, 0x80, 0x52, // mov w20, #20
|
||
0x10, 0x04, 0x14, 0x8B, // add w16, w16, w20
|
||
0x50, 0x00, 0x80, 0x52, // mov w16, #5
|
||
0x10, 0x04, 0x10, 0x8B, // add w16, w16, w16
|
||
0x10, 0x04, 0x14, 0xCB, // sub w16, w16, w20
|
||
0xC0, 0x03, 0x5F, 0xD6, // ret
|
||
]
|
||
}
|
||
|
||
/// 创建RISC-V测试代码
|
||
fn create_test_code_riscv() -> Vec<u8> {
|
||
vec![
|
||
0x0A, 0x00, 0x00, 0x93, // addi x19, x0, 10
|
||
0x14, 0x00, 0x00, 0x13, // addi x2, x0, 20
|
||
0x13, 0x04, 0x02, 0x13, // addi x19, x19, 2
|
||
0x93, 0x0A, 0x00, 0x00, // addi x19, x0, 10
|
||
0x93, 0x04, 0x02, 0x13, // addi x19, x19, 2
|
||
0x33, 0x04, 0x12, 0x41, // sub x19, x19, x2
|
||
0x67, 0x80, 0x00, 0x00, // jalr x0, 0(x1)
|
||
]
|
||
}
|
||
|
||
/// 创建复杂测试代码
|
||
fn create_complex_test_code(complexity: usize) -> Vec<u8> {
|
||
let mut code = Vec::new();
|
||
|
||
// 添加更多指令以增加复杂度
|
||
for i in 0..complexity {
|
||
match i % 8 {
|
||
0 => code.extend_from_slice(&[0xB8, (i % 256) as u8, ((i >> 8) % 256) as u8, 0, 0]), // mov eax, i
|
||
1 => code.extend_from_slice(&[0xBB, ((i + 1) % 256) as u8, (((i + 1) >> 8) % 256) as u8, 0, 0]), // mov ebx, i+1
|
||
2 => code.extend_from_slice(&[0x01, 0xD8]), // add eax, ebx
|
||
3 => code.extend_from_slice(&[0x83, 0xC0, 0x05]), // add eax, 5
|
||
4 => code.extend_from_slice(&[0x29, 0xD8]), // sub eax, ebx
|
||
5 => code.extend_from_slice(&[0x89, 0xC2]), // mov edx, eax
|
||
6 => code.extend_from_slice(&[0x83, 0xC2, 0x0A]), // add edx, 10
|
||
7 => code.extend_from_slice(&[0x89, 0xD0]), // mov eax, edx
|
||
_ => {}
|
||
}
|
||
}
|
||
|
||
code.extend_from_slice(&[0xC3]); // ret
|
||
code
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_cross_arch_performance() {
|
||
let mut framework = PerformanceStressTestFramework::new();
|
||
let result = framework.run_cross_arch_performance_test();
|
||
|
||
assert!(result.operations > 0);
|
||
assert!(result.throughput_ops_per_sec > 0.0);
|
||
println!("Cross-arch performance test: {} ops in {} ms",
|
||
result.operations, result.execution_time_ms);
|
||
}
|
||
|
||
#[test]
|
||
fn test_jit_compilation_stress() {
|
||
let mut framework = PerformanceStressTestFramework::new();
|
||
let config = StressTestConfig {
|
||
duration_seconds: 5, // 短时间测试
|
||
thread_count: 2,
|
||
operation_interval_us: Some(1000), // 1ms间隔
|
||
memory_pressure_level: 3,
|
||
cpu_pressure_level: 3,
|
||
};
|
||
|
||
let result = framework.run_jit_compilation_stress_test(config);
|
||
|
||
assert!(result.operations > 0);
|
||
assert!(result.throughput_ops_per_sec > 0.0);
|
||
println!("JIT compilation stress test: {} ops in {} ms",
|
||
result.operations, result.execution_time_ms);
|
||
}
|
||
|
||
#[test]
|
||
fn test_memory_stress() {
|
||
let mut framework = PerformanceStressTestFramework::new();
|
||
let config = StressTestConfig {
|
||
duration_seconds: 5, // 短时间测试
|
||
thread_count: 2,
|
||
operation_interval_us: Some(1000), // 1ms间隔
|
||
memory_pressure_level: 3,
|
||
cpu_pressure_level: 1,
|
||
};
|
||
|
||
let result = framework.run_memory_stress_test(config);
|
||
|
||
assert!(result.operations > 0);
|
||
assert!(result.throughput_ops_per_sec > 0.0);
|
||
println!("Memory stress test: {} ops in {} ms",
|
||
result.operations, result.execution_time_ms);
|
||
}
|
||
|
||
#[test]
|
||
fn test_concurrent_execution_stress() {
|
||
let mut framework = PerformanceStressTestFramework::new();
|
||
let config = StressTestConfig {
|
||
duration_seconds: 5, // 短时间测试
|
||
thread_count: 2,
|
||
operation_interval_us: Some(1000), // 1ms间隔
|
||
memory_pressure_level: 1,
|
||
cpu_pressure_level: 3,
|
||
};
|
||
|
||
let result = framework.run_concurrent_execution_stress_test(config);
|
||
|
||
assert!(result.operations > 0);
|
||
assert!(result.throughput_ops_per_sec > 0.0);
|
||
println!("Concurrent execution stress test: {} ops in {} ms",
|
||
result.operations, result.execution_time_ms);
|
||
}
|
||
|
||
#[test]
|
||
fn test_resource_leak_detection() {
|
||
let mut framework = PerformanceStressTestFramework::new();
|
||
let result = framework.run_resource_leak_test();
|
||
|
||
assert!(result.operations > 0);
|
||
// 检查内存泄漏是否在合理范围内(小于10MB)
|
||
assert!(result.memory_usage_bytes < 10 * 1024 * 1024);
|
||
println!("Resource leak test: {} ops, {} bytes leaked",
|
||
result.operations, result.memory_usage_bytes);
|
||
}
|
||
|
||
#[test]
|
||
fn test_long_term_stability() {
|
||
let mut framework = PerformanceStressTestFramework::new();
|
||
// 短时间测试,实际使用时可以设置更长的时间
|
||
let result = framework.run_long_term_stability_test(0); // 0小时,仅测试功能
|
||
|
||
assert!(result.operations > 0);
|
||
assert!(result.throughput_ops_per_sec > 0.0);
|
||
println!("Long-term stability test: {} ops in {} ms",
|
||
result.operations, result.execution_time_ms);
|
||
}
|
||
|
||
#[test]
|
||
fn test_comprehensive_stress_suite() {
|
||
let mut framework = PerformanceStressTestFramework::new();
|
||
|
||
// 运行所有测试
|
||
let cross_arch_result = framework.run_cross_arch_performance_test();
|
||
let leak_result = framework.run_resource_leak_test();
|
||
|
||
let config = StressTestConfig {
|
||
duration_seconds: 3,
|
||
thread_count: 2,
|
||
operation_interval_us: Some(1000),
|
||
memory_pressure_level: 3,
|
||
cpu_pressure_level: 3,
|
||
};
|
||
|
||
let jit_result = framework.run_jit_compilation_stress_test(config.clone());
|
||
let memory_result = framework.run_memory_stress_test(config.clone());
|
||
let concurrent_result = framework.run_concurrent_execution_stress_test(config);
|
||
|
||
// 打印所有结果
|
||
framework.print_results();
|
||
|
||
// 生成报告
|
||
let report = framework.generate_report();
|
||
println!("Generated report:\n{}", report);
|
||
|
||
// 验证所有测试都有操作
|
||
assert!(cross_arch_result.operations > 0);
|
||
assert!(jit_result.operations > 0);
|
||
assert!(memory_result.operations > 0);
|
||
assert!(concurrent_result.operations > 0);
|
||
assert!(leak_result.operations > 0);
|
||
|
||
// 验证所有测试都有吞吐量
|
||
assert!(cross_arch_result.throughput_ops_per_sec > 0.0);
|
||
assert!(jit_result.throughput_ops_per_sec > 0.0);
|
||
assert!(memory_result.throughput_ops_per_sec > 0.0);
|
||
assert!(concurrent_result.throughput_ops_per_sec > 0.0);
|
||
assert!(leak_result.throughput_ops_per_sec > 0.0);
|
||
}
|
||
} |