use std::time::Duration;
pub fn configure_for_server_memory_benchmarks(group: &mut criterion::BenchmarkGroup<criterion::measurement::WallTime>) {
#[cfg(target_arch = "x86_64")]
{
group.sample_size(5000); group.measurement_time(Duration::from_secs(180)); group.warm_up_time(Duration::from_secs(30)); group.confidence_level(0.95); group.noise_threshold(0.005); group.significance_level(0.01); }
#[cfg(target_arch = "aarch64")]
{
group.sample_size(3000);
group.measurement_time(Duration::from_secs(120));
group.warm_up_time(Duration::from_secs(20));
group.confidence_level(0.95);
group.noise_threshold(0.01);
group.significance_level(0.01);
}
}
pub fn configure_for_server_cpu_benchmarks(group: &mut criterion::BenchmarkGroup<criterion::measurement::WallTime>) {
#[cfg(target_arch = "x86_64")]
{
group.sample_size(10000); group.measurement_time(Duration::from_secs(240)); group.warm_up_time(Duration::from_secs(20));
group.confidence_level(0.99); group.noise_threshold(0.002); group.significance_level(0.005); }
#[cfg(target_arch = "aarch64")]
{
group.sample_size(7000);
group.measurement_time(Duration::from_secs(180));
group.warm_up_time(Duration::from_secs(15));
group.confidence_level(0.99);
group.noise_threshold(0.005);
group.significance_level(0.01);
}
}
pub fn prewarm_server_subsystems() {
println!("🔥 Pre-warming server subsystems...");
for node in 0..get_numa_node_count() {
if let Ok(_) = std::process::Command::new("numactl")
.args([&format!("--cpunodebind={node}"), "--membind", &node.to_string()])
.args(["echo", "warming", "node"])
.output()
{
let sizes = [1024, 4096, 16384, 65536];
for &size in &sizes {
let vec = vec![0u8; size];
std::hint::black_box(&vec);
drop(vec);
}
}
}
for _ in 0..1000 {
let data: Vec<u64> = (0..1000).collect();
let _sum: u64 = data.iter().sum();
std::hint::black_box(_sum);
}
for _ in 0..100 {
let _ = std::time::SystemTime::now();
std::thread::yield_now();
}
std::thread::sleep(Duration::from_secs(5));
println!("✅ Server subsystems warmed up");
}
pub fn check_server_environment() -> ServerEnvironment {
let mut issues = Vec::new();
let mut warnings = Vec::new();
let mut info = std::collections::HashMap::new();
if is_virtualized() {
issues.push("Running on virtualized hardware - not optimal for HFT".to_string());
}
let cpu_count = num_cpus::get();
info.insert("cpu_count".to_string(), cpu_count.to_string());
if cpu_count < 8 {
warnings.push(format!("Low CPU count: {cpu_count} (recommended: 16+)"));
}
let (total_mem_gb, available_mem_gb) = get_memory_info();
info.insert("total_memory_gb".to_string(), format!("{total_mem_gb:.1}"));
info.insert("available_memory_gb".to_string(), format!("{available_mem_gb:.1}"));
if total_mem_gb < 16.0 {
warnings.push(format!("Low total memory: {total_mem_gb:.1}GB (recommended: 32GB+)"));
}
if available_mem_gb < 8.0 {
issues.push(format!("Low available memory: {available_mem_gb:.1}GB"));
}
if let Some(governor) = get_cpu_governor() {
info.insert("cpu_governor".to_string(), governor.clone());
if governor != "performance" {
warnings.push(format!("CPU governor not optimal: {governor} (should be 'performance')"));
}
}
let load_avg = get_load_average();
info.insert("load_average".to_string(), format!("{load_avg:.2}"));
if load_avg > 2.0 {
warnings.push(format!("High system load: {load_avg:.2}"));
}
let numa_nodes = get_numa_node_count();
info.insert("numa_nodes".to_string(), numa_nodes.to_string());
if numa_nodes > 1 {
info.insert("numa_topology".to_string(), "detected".to_string());
}
ServerEnvironment {
is_optimal: issues.is_empty(),
issues,
warnings,
info,
}
}
pub struct ServerEnvironment {
pub is_optimal: bool,
pub issues: Vec<String>,
pub warnings: Vec<String>,
pub info: std::collections::HashMap<String, String>,
}
impl ServerEnvironment {
pub fn print_detailed_report(&self) {
println!("🖥️ Server Benchmark Environment Report");
println!("=======================================");
println!("\n📊 System Information:");
for (key, value) in &self.info {
println!(" {}: {}", key.replace('_', " "), value);
}
if self.is_optimal {
println!("\n✅ OPTIMAL: Server environment is ideal for HFT benchmarking");
} else {
println!("\n❌ ISSUES DETECTED: Server environment has problems");
}
if !self.issues.is_empty() {
println!("\n❌ Critical Issues:");
for issue in &self.issues {
println!(" - {issue}");
}
}
if !self.warnings.is_empty() {
println!("\n⚠️ Warnings:");
for warning in &self.warnings {
println!(" - {warning}");
}
}
if !self.is_optimal || !self.warnings.is_empty() {
println!("\n💡 Recommendations:");
println!(" - Run with: sudo ./scripts/server-benchmark-setup.sh run");
println!(" - Ensure bare metal (no virtualization)");
println!(" - Set CPU governor to 'performance'");
println!(" - Stop non-essential services");
println!(" - Use CPU isolation and NUMA binding");
}
println!("=======================================");
}
}
fn is_virtualized() -> bool {
std::fs::read_to_string("/proc/cpuinfo")
.map(|content| content.contains("hypervisor"))
.unwrap_or(false)
|| std::path::Path::new("/proc/xen").exists()
|| std::path::Path::new("/sys/hypervisor/uuid").exists()
}
fn get_memory_info() -> (f64, f64) {
if let Ok(meminfo) = std::fs::read_to_string("/proc/meminfo") {
let mut total_kb = 0u64;
let mut available_kb = 0u64;
for line in meminfo.lines() {
if line.starts_with("MemTotal:") {
total_kb = line.split_whitespace().nth(1)
.and_then(|s| s.parse().ok())
.unwrap_or(0);
} else if line.starts_with("MemAvailable:") {
available_kb = line.split_whitespace().nth(1)
.and_then(|s| s.parse().ok())
.unwrap_or(0);
}
}
(
total_kb as f64 / 1024.0 / 1024.0, available_kb as f64 / 1024.0 / 1024.0,
)
} else {
(0.0, 0.0)
}
}
fn get_cpu_governor() -> Option<String> {
std::fs::read_to_string("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor")
.ok()
.map(|s| s.trim().to_string())
}
fn get_load_average() -> f64 {
std::fs::read_to_string("/proc/loadavg")
.ok()
.and_then(|content| {
content.split_whitespace()
.next()
.and_then(|s| s.parse().ok())
})
.unwrap_or(0.0)
}
fn get_numa_node_count() -> usize {
std::process::Command::new("numactl")
.args(["--hardware"])
.output()
.ok()
.and_then(|output| {
let output_str = String::from_utf8_lossy(&output.stdout);
output_str.lines()
.find(|line| line.contains("available:"))
.and_then(|line| {
line.split_whitespace()
.nth(1)
.and_then(|s| s.parse().ok())
})
})
.unwrap_or(1)
}