//! RDTSC Performance Validation Tests //! //! This module implements REAL hardware-level performance testing using RDTSC (Read Time-Stamp Counter) //! to validate the Foxhunt HFT system meets its <14ns latency requirements. //! //! ## Test Coverage: //! 1. **RDTSC Precision Testing**: Validate timing accuracy to nanosecond level //! 2. **Lock-free Operations**: Test atomic operations and lock-free data structures //! 3. **SIMD Performance**: Validate vectorized operations meet performance targets //! 4. **CPU Cache Performance**: Test memory access patterns and cache efficiency //! 5. **Memory Allocation**: Test allocation patterns and performance //! 6. **Network I/O Latency**: Measure network stack performance //! //! ## Performance Targets: //! - RDTSC timing resolution: <14ns //! - Lock-free queue operations: <100ns //! - SIMD operations: <1Ξs //! - Cache miss penalty: <50ns //! - Memory allocation: <100ns //! - Network round-trip: <50Ξs #![warn(missing_docs)] #![warn(clippy::all)] #![allow(clippy::too_many_arguments)] #![allow(unused_crate_dependencies)] use criterion::black_box; use std::arch::x86_64::*; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; use std::time::{Duration, Instant}; use tracing::{info, warn}; /// RDTSC performance validation test suite pub struct RdtscPerformanceValidator { /// Number of iterations for statistical significance iterations: usize, /// TSC frequency for time conversion tsc_frequency: u64, /// Test results storage results: Vec, } /// Individual performance test result #[derive(Debug, Clone)] pub struct PerformanceTestResult { /// Test name pub name: String, /// Measured latency in nanoseconds pub latency_ns: u64, /// Whether test passed the target pub passed: bool, /// Target latency in nanoseconds pub target_ns: u64, /// Number of samples taken pub samples: usize, /// Standard deviation of measurements pub std_dev_ns: f64, /// Percentile measurements pub percentiles: PerformancePercentiles, } /// Performance percentile measurements #[derive(Debug, Clone)] pub struct PerformancePercentiles { /// 50th percentile (median) pub p50_ns: u64, /// 95th percentile pub p95_ns: u64, /// 99th percentile pub p99_ns: u64, /// 99.9th percentile pub p999_ns: u64, /// Maximum measurement pub max_ns: u64, /// Minimum measurement pub min_ns: u64, } impl RdtscPerformanceValidator { /// Create a new RDTSC performance validator pub fn new() -> Result> { let iterations = 100_000; // Large sample size for statistical significance let tsc_frequency = Self::calibrate_tsc_frequency()?; info!("Initialized RDTSC Performance Validator"); info!("TSC Frequency: {} Hz", tsc_frequency); info!("Test iterations: {}", iterations); Ok(Self { iterations, tsc_frequency, results: Vec::new(), }) } /// Run comprehensive RDTSC performance validation pub async fn run_comprehensive_validation(&mut self) -> Result<(), Box> { info!("🚀 Starting comprehensive RDTSC performance validation"); // Warm up the CPU and stabilize frequency self.cpu_warmup().await?; // Test 1: RDTSC timing precision info!("Test 1/6: RDTSC timing precision"); self.test_rdtsc_precision().await?; // Test 2: Lock-free atomic operations info!("Test 2/6: Lock-free atomic operations"); self.test_lockfree_operations().await?; // Test 3: SIMD vectorized operations info!("Test 3/6: SIMD vectorized operations"); self.test_simd_operations().await?; // Test 4: CPU cache performance info!("Test 4/6: CPU cache performance"); self.test_cache_performance().await?; // Test 5: Memory allocation performance info!("Test 5/6: Memory allocation performance"); self.test_memory_allocation().await?; // Test 6: Network I/O latency info!("Test 6/6: Network I/O latency"); self.test_network_io().await?; // Generate comprehensive report self.generate_performance_report().await?; Ok(()) } /// Test RDTSC timing precision async fn test_rdtsc_precision(&mut self) -> Result<(), Box> { let mut measurements = Vec::with_capacity(self.iterations); for _ in 0..self.iterations { let start_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects // Minimal operation to measure timing resolution black_box(1 + 1); let end_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects let cycles = end_tsc - start_tsc; let nanoseconds = self.cycles_to_nanoseconds(cycles); measurements.push(nanoseconds); } let result = self.analyze_measurements("RDTSC Precision", &measurements, 14)?; self.results.push(result.clone()); if result.passed { info!( "✅ RDTSC precision: {}ns (target: <14ns)", result.latency_ns ); } else { warn!( "⚠ïļ RDTSC precision: {}ns (target: <14ns)", result.latency_ns ); } Ok(()) } /// Test lock-free atomic operations async fn test_lockfree_operations(&mut self) -> Result<(), Box> { let counter = Arc::new(AtomicU64::new(0)); let mut measurements = Vec::with_capacity(self.iterations); for _ in 0..self.iterations { let start_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects // Atomic increment operation counter.fetch_add(1, Ordering::Relaxed); let end_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects let cycles = end_tsc - start_tsc; let nanoseconds = self.cycles_to_nanoseconds(cycles); measurements.push(nanoseconds); } let result = self.analyze_measurements("Lock-free Atomic Operations", &measurements, 100)?; self.results.push(result.clone()); if result.passed { info!( "✅ Lock-free operations: {}ns (target: <100ns)", result.latency_ns ); } else { warn!( "⚠ïļ Lock-free operations: {}ns (target: <100ns)", result.latency_ns ); } Ok(()) } /// Test SIMD vectorized operations async fn test_simd_operations(&mut self) -> Result<(), Box> { // Check for AVX2 support if !is_x86_feature_detected!("avx2") { warn!("AVX2 not supported, skipping SIMD tests"); return Ok(()); } let data = vec![1.0f32; 256]; // 256 floats for AVX2 processing let mut measurements = Vec::with_capacity(self.iterations); for _ in 0..self.iterations { let start_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects // SIMD vector addition // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects unsafe { self.simd_vector_add(&data); } let end_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects let cycles = end_tsc - start_tsc; let nanoseconds = self.cycles_to_nanoseconds(cycles); measurements.push(nanoseconds); } let result = self.analyze_measurements("SIMD Operations", &measurements, 1000)?; self.results.push(result.clone()); if result.passed { info!( "✅ SIMD operations: {}ns (target: <1000ns)", result.latency_ns ); } else { warn!( "⚠ïļ SIMD operations: {}ns (target: <1000ns)", result.latency_ns ); } Ok(()) } /// Test CPU cache performance async fn test_cache_performance(&mut self) -> Result<(), Box> { // Test L1 cache performance with sequential access let cache_line_size = 64; let l1_cache_size = 32 * 1024; // 32KB typical L1 cache let data_size = l1_cache_size / std::mem::size_of::(); let data = vec![0u64; data_size]; let mut measurements = Vec::with_capacity(self.iterations); for _ in 0..self.iterations { let start_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects // Sequential memory access pattern (cache-friendly) let mut sum = 0u64; for i in (0..data.len()).step_by(cache_line_size / std::mem::size_of::()) { sum = sum.wrapping_add(unsafe { *data.get_unchecked(i) }); // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects } black_box(sum); let end_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects let cycles = end_tsc - start_tsc; let nanoseconds = self.cycles_to_nanoseconds(cycles); measurements.push(nanoseconds); } let result = self.analyze_measurements("Cache Performance", &measurements, 50)?; self.results.push(result.clone()); if result.passed { info!( "✅ Cache performance: {}ns (target: <50ns)", result.latency_ns ); } else { warn!( "⚠ïļ Cache performance: {}ns (target: <50ns)", result.latency_ns ); } Ok(()) } /// Test memory allocation performance async fn test_memory_allocation(&mut self) -> Result<(), Box> { let mut measurements = Vec::with_capacity(self.iterations); for _ in 0..self.iterations { let start_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects // Small allocation typical for HFT operations let _data: Vec = Vec::with_capacity(64); let end_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects let cycles = end_tsc - start_tsc; let nanoseconds = self.cycles_to_nanoseconds(cycles); measurements.push(nanoseconds); } let result = self.analyze_measurements("Memory Allocation", &measurements, 100)?; self.results.push(result.clone()); if result.passed { info!( "✅ Memory allocation: {}ns (target: <100ns)", result.latency_ns ); } else { warn!( "⚠ïļ Memory allocation: {}ns (target: <100ns)", result.latency_ns ); } Ok(()) } /// Test network I/O latency (localhost loopback) async fn test_network_io(&mut self) -> Result<(), Box> { use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::{TcpListener, TcpStream}; // Start a simple echo server let listener = TcpListener::bind("127.0.0.1:0").await?; let addr = listener.local_addr()?; let server_handle = tokio::spawn(async move { while let Ok((mut socket, _)) = listener.accept().await { tokio::spawn(async move { let mut buf = [0; 8]; if socket.read_exact(&mut buf).await.is_ok() { let _ = socket.write_all(&buf).await; } }); } }); // Give server time to start tokio::time::sleep(Duration::from_millis(10)).await; let mut measurements = Vec::with_capacity(1000); // Fewer iterations for network I/O for _ in 0..1000 { let start_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects // Connect and send/receive data if let Ok(mut stream) = TcpStream::connect(addr).await { let test_data = [0x42u8; 8]; if stream.write_all(&test_data).await.is_ok() { let mut response = [0u8; 8]; let _ = stream.read_exact(&mut response).await; } } let end_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects let cycles = end_tsc - start_tsc; let nanoseconds = self.cycles_to_nanoseconds(cycles); measurements.push(nanoseconds); } server_handle.abort(); let result = self.analyze_measurements("Network I/O", &measurements, 50000)?; self.results.push(result.clone()); if result.passed { info!("✅ Network I/O: {}ns (target: <50000ns)", result.latency_ns); } else { warn!( "⚠ïļ Network I/O: {}ns (target: <50000ns)", result.latency_ns ); } Ok(()) } /// Analyze measurement data and calculate statistics fn analyze_measurements( &self, name: &str, measurements: &[u64], target_ns: u64, ) -> Result> { if measurements.is_empty() { return Err("No measurements available".into()); } let mut sorted = measurements.to_vec(); sorted.sort_unstable(); let sum: u64 = measurements.iter().sum(); let mean = sum / measurements.len() as u64; let variance = measurements .iter() .map(|&x| { let diff = x as f64 - mean as f64; diff * diff }) .sum::() / measurements.len() as f64; let std_dev = variance.sqrt(); let percentiles = PerformancePercentiles { p50_ns: sorted[sorted.len() * 50 / 100], p95_ns: sorted[sorted.len() * 95 / 100], p99_ns: sorted[sorted.len() * 99 / 100], p999_ns: sorted[sorted.len() * 999 / 1000], max_ns: sorted[sorted.len() - 1], min_ns: sorted[0], }; let result = PerformanceTestResult { name: name.to_string(), latency_ns: percentiles.p95_ns, // Use P95 for pass/fail determination passed: percentiles.p95_ns <= target_ns, target_ns, samples: measurements.len(), std_dev_ns: std_dev, percentiles, }; Ok(result) } /// Generate comprehensive performance report async fn generate_performance_report(&self) -> Result<(), Box> { info!("📊 RDTSC Performance Validation Report"); info!("====================================="); let mut total_tests = 0; let mut passed_tests = 0; for result in &self.results { total_tests += 1; if result.passed { passed_tests += 1; } let status = if result.passed { "✅ PASS" } else { "❌ FAIL" }; info!("{} - {}", status, result.name); info!( " P50: {}ns, P95: {}ns, P99: {}ns, P99.9: {}ns", result.percentiles.p50_ns, result.percentiles.p95_ns, result.percentiles.p99_ns, result.percentiles.p999_ns ); info!( " Target: {}ns, Samples: {}, StdDev: {:.2}ns", result.target_ns, result.samples, result.std_dev_ns ); info!(""); } let success_rate = (passed_tests as f64 / total_tests as f64) * 100.0; info!( "Overall Results: {}/{} tests passed ({:.1}%)", passed_tests, total_tests, success_rate ); if passed_tests == total_tests { info!("🎉 All performance tests PASSED - System meets HFT requirements!"); } else { warn!("⚠ïļ Some performance tests FAILED - Review system configuration"); } Ok(()) } /// CPU warmup to stabilize frequency and cache state async fn cpu_warmup(&self) -> Result<(), Box> { info!("Warming up CPU and stabilizing frequency..."); let warmup_start = Instant::now(); let warmup_duration = Duration::from_secs(2); while warmup_start.elapsed() < warmup_duration { // CPU-intensive work to boost frequency let mut sum = 0u64; for i in 0..10000 { sum = sum.wrapping_add(i); } black_box(sum); } info!("CPU warmup completed"); Ok(()) } /// Calibrate TSC frequency fn calibrate_tsc_frequency() -> Result> { let start_time = Instant::now(); let start_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects std::thread::sleep(Duration::from_millis(100)); let end_time = Instant::now(); let end_tsc = unsafe { _rdtsc() }; // SAFETY: RDTSC instruction only reads CPU timestamp counter with no side effects let elapsed_ns = (end_time - start_time).as_nanos() as u64; let elapsed_cycles = end_tsc - start_tsc; let frequency = (elapsed_cycles * 1_000_000_000) / elapsed_ns; Ok(frequency) } /// Convert TSC cycles to nanoseconds fn cycles_to_nanoseconds(&self, cycles: u64) -> u64 { (cycles * 1_000_000_000) / self.tsc_frequency } /// SIMD vector addition using AVX2 #[target_feature(enable = "avx2")] unsafe fn simd_vector_add(&self, data: &[f32]) { let chunks = data.chunks_exact(8); for chunk in chunks { let a = _mm256_loadu_ps(chunk.as_ptr()); let b = _mm256_set1_ps(1.0); let result = _mm256_add_ps(a, b); black_box(result); } } } /// Run RDTSC performance validation tests #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn test_rdtsc_performance_validation() { let mut validator = RdtscPerformanceValidator::new().expect("Failed to create RDTSC validator"); validator .run_comprehensive_validation() .await .expect("RDTSC performance validation failed"); // Check that critical tests pass let critical_tests = ["RDTSC Precision", "Lock-free Atomic Operations"]; for test_name in &critical_tests { let result = validator .results .iter() .find(|r| r.name == *test_name) .expect(&format!("Test '{}' not found", test_name)); assert!( result.passed, "Critical test '{}' failed: {}ns > {}ns target", test_name, result.latency_ns, result.target_ns ); } } #[tokio::test] async fn test_individual_rdtsc_precision() { let mut validator = RdtscPerformanceValidator::new().expect("Failed to create RDTSC validator"); validator .test_rdtsc_precision() .await .expect("RDTSC precision test failed"); let result = &validator.results[0]; assert_eq!(result.name, "RDTSC Precision"); // RDTSC should provide sub-nanosecond precision on modern CPUs // but we allow up to 14ns due to system variability info!("RDTSC precision: {}ns (target: <14ns)", result.latency_ns); } #[tokio::test] async fn test_simd_operations() { if !is_x86_feature_detected!("avx2") { println!("Skipping SIMD test - AVX2 not supported"); return; } let mut validator = RdtscPerformanceValidator::new().expect("Failed to create RDTSC validator"); validator .test_simd_operations() .await .expect("SIMD operations test failed"); let result = &validator.results[0]; assert_eq!(result.name, "SIMD Operations"); info!("SIMD operations: {}ns (target: <1000ns)", result.latency_ns); } }