use scirs2_core::parallel_ops::{IndexedParallelIterator, ParallelIterator};
use scirs2_core::Complex64;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::{Duration, Instant};
use quantrs2_circuit::builder::{Circuit, Simulator};
use quantrs2_core::{error::QuantRS2Result, platform::PlatformCapabilities, qubit::QubitId};
use crate::circuit_optimization::{CircuitOptimizer, OptimizationConfig};
use crate::optimized_simd;
use crate::statevector::StateVectorSimulator;
#[derive(Debug)]
pub struct QuantumBenchmarkSuite {
config: BenchmarkConfig,
results: Vec<BenchmarkResult>,
system_info: SystemInfo,
}
#[derive(Debug, Clone)]
pub struct BenchmarkConfig {
pub qubit_range: std::ops::Range<usize>,
pub iterations: usize,
pub profile_memory: bool,
pub compare_optimizations: bool,
pub scalability_analysis: bool,
pub warmup_iterations: usize,
pub max_circuit_depth: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BenchmarkResult {
pub name: String,
pub qubits: usize,
pub depth: usize,
pub timing: TimingStats,
pub memory: MemoryStats,
pub throughput: ThroughputStats,
pub config_description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimingStats {
pub average_ns: u128,
pub min_ns: u128,
pub max_ns: u128,
pub std_dev_ns: f64,
pub p95_ns: u128,
pub p99_ns: u128,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryStats {
pub peak_memory_bytes: usize,
pub average_memory_bytes: usize,
pub efficiency_score: f64,
pub buffer_pool_utilization: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThroughputStats {
pub gates_per_second: f64,
pub qubits_per_second: f64,
pub operations_per_second: f64,
pub steps_per_second: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemInfo {
pub cpu_info: String,
pub total_memory_gb: f64,
pub cpu_cores: usize,
pub rust_version: String,
pub optimization_level: String,
pub simd_support: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BenchmarkComparison {
pub baseline: String,
pub comparison: String,
pub improvement_ratio: f64,
pub memory_improvement: f64,
pub throughput_improvement: f64,
pub scalability_factor: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScalabilityAnalysis {
pub time_growth_factor: f64,
pub memory_growth_factor: f64,
pub max_practical_qubits: usize,
pub efficiency_plateau: usize,
pub complexity_class: String,
}
impl Default for BenchmarkConfig {
fn default() -> Self {
Self {
qubit_range: 1..20,
iterations: 10,
profile_memory: true,
compare_optimizations: true,
scalability_analysis: true,
warmup_iterations: 3,
max_circuit_depth: 50,
}
}
}
impl QuantumBenchmarkSuite {
#[must_use]
pub fn new(config: BenchmarkConfig) -> Self {
Self {
config,
results: Vec::new(),
system_info: Self::gather_system_info(),
}
}
pub fn run_all_benchmarks(&mut self) -> QuantRS2Result<()> {
println!("🚀 Starting Comprehensive Quantum Simulation Benchmarks");
println!("========================================================\n");
self.print_system_info();
self.benchmark_basic_gates()?;
self.benchmark_circuit_execution()?;
self.benchmark_memory_efficiency()?;
if self.config.compare_optimizations {
self.benchmark_optimization_comparison()?;
}
if self.config.scalability_analysis {
self.benchmark_scalability()?;
}
self.benchmark_simd_performance()?;
self.benchmark_circuit_optimization()?;
self.generate_final_report();
Ok(())
}
pub fn benchmark_basic_gates(&mut self) -> QuantRS2Result<()> {
println!("🔧 Benchmarking Basic Gate Operations");
println!("------------------------------------");
let gates = vec![
(
"Hadamard",
Box::new(|circuit: &mut Circuit<16>, q: usize| {
circuit.h(QubitId::new(q as u32))?;
Ok(())
}) as Box<dyn Fn(&mut Circuit<16>, usize) -> QuantRS2Result<()>>,
),
(
"Pauli-X",
Box::new(|circuit: &mut Circuit<16>, q: usize| {
circuit.x(QubitId::new(q as u32))?;
Ok(())
}),
),
(
"Pauli-Y",
Box::new(|circuit: &mut Circuit<16>, q: usize| {
circuit.y(QubitId::new(q as u32))?;
Ok(())
}),
),
(
"Pauli-Z",
Box::new(|circuit: &mut Circuit<16>, q: usize| {
circuit.z(QubitId::new(q as u32))?;
Ok(())
}),
),
(
"Phase-S",
Box::new(|circuit: &mut Circuit<16>, q: usize| {
circuit.s(QubitId::new(q as u32))?;
Ok(())
}),
),
(
"T-Gate",
Box::new(|circuit: &mut Circuit<16>, q: usize| {
circuit.t(QubitId::new(q as u32))?;
Ok(())
}),
),
];
for (gate_name, gate_fn) in gates {
for qubits in [4, 8, 12, 16] {
let result = self.benchmark_gate_operation(gate_name, qubits, &gate_fn)?;
self.results.push(result);
println!(
" ✓ {} on {} qubits: {:.2}ms",
gate_name,
qubits,
self.results
.last()
.expect("results should not be empty after push")
.timing
.average_ns as f64
/ 1_000_000.0
);
}
}
println!();
Ok(())
}
pub fn benchmark_circuit_execution(&mut self) -> QuantRS2Result<()> {
println!("⚡ Benchmarking Circuit Execution");
println!("--------------------------------");
for qubits in self.config.qubit_range.clone().step_by(2) {
if qubits > 16 {
break;
}
let result = self.benchmark_random_circuit(qubits, 20)?;
self.results.push(result);
println!(
" ✓ Random circuit {} qubits: {:.2}ms",
qubits,
self.results
.last()
.expect("results should not be empty after push")
.timing
.average_ns as f64
/ 1_000_000.0
);
}
println!();
Ok(())
}
pub fn benchmark_memory_efficiency(&mut self) -> QuantRS2Result<()> {
println!("💾 Benchmarking Memory Efficiency");
println!("--------------------------------");
let configs = vec![
("Standard", StateVectorSimulator::new()),
("High-Performance", StateVectorSimulator::high_performance()),
("Sequential", StateVectorSimulator::sequential()),
];
for (config_name, simulator) in configs {
for qubits in [8, 12, 16] {
let result = self.benchmark_memory_usage(config_name, qubits, &simulator)?;
self.results.push(result);
println!(
" ✓ {} config {} qubits: {:.1}MB peak",
config_name,
qubits,
self.results
.last()
.expect("results should not be empty after push")
.memory
.peak_memory_bytes as f64
/ 1_048_576.0
);
}
}
println!();
Ok(())
}
pub fn benchmark_optimization_comparison(&mut self) -> QuantRS2Result<()> {
println!("🔄 Benchmarking Optimization Strategies");
println!("--------------------------------------");
let optimization_configs = vec![
(
"No Optimization",
OptimizationConfig {
enable_gate_fusion: false,
enable_redundant_elimination: false,
enable_commutation_reordering: false,
enable_single_qubit_optimization: false,
enable_two_qubit_optimization: false,
max_passes: 0,
enable_depth_reduction: false,
},
),
(
"Conservative",
OptimizationConfig {
enable_gate_fusion: false,
enable_redundant_elimination: true,
enable_commutation_reordering: false,
enable_single_qubit_optimization: false,
enable_two_qubit_optimization: false,
max_passes: 1,
enable_depth_reduction: false,
},
),
("Aggressive", OptimizationConfig::default()),
];
for (opt_name, opt_config) in optimization_configs {
for qubits in [8, 12, 16] {
let result = self.benchmark_optimization_strategy(opt_name, qubits, &opt_config)?;
self.results.push(result);
println!(
" ✓ {} optimization {} qubits: {:.2}ms",
opt_name,
qubits,
self.results
.last()
.expect("results should not be empty after push")
.timing
.average_ns as f64
/ 1_000_000.0
);
}
}
println!();
Ok(())
}
fn benchmark_scalability(&self) -> QuantRS2Result<()> {
println!("📈 Analyzing Scalability");
println!("-----------------------");
let mut scalability_data = Vec::new();
for qubits in (4..=20).step_by(2) {
let start = Instant::now();
let circuit = self.create_test_circuit(qubits, 10)?;
let simulator = StateVectorSimulator::new();
for _ in 0..self.config.warmup_iterations {
let _ = simulator.run(&circuit);
}
let mut times = Vec::new();
for _ in 0..self.config.iterations {
let bench_start = Instant::now();
let _ = simulator.run(&circuit)?;
times.push(bench_start.elapsed());
}
let avg_time = times.iter().sum::<Duration>() / times.len() as u32;
scalability_data.push((qubits, avg_time));
println!(
" ✓ {} qubits: {:.2}ms",
qubits,
avg_time.as_secs_f64() * 1000.0
);
if avg_time > Duration::from_secs(10) {
println!(" ⚠️ Breaking at {qubits} qubits due to time limit");
break;
}
}
let analysis = self.analyze_scalability(&scalability_data);
println!(
" 📊 Growth factor: {:.2}x per qubit",
analysis.time_growth_factor
);
println!(
" 🎯 Max practical qubits: {}",
analysis.max_practical_qubits
);
println!();
Ok(())
}
fn benchmark_simd_performance(&self) -> QuantRS2Result<()> {
println!("🏎️ Benchmarking SIMD Performance");
println!("--------------------------------");
let test_sizes = vec![1024, 4096, 16_384, 65_536];
for size in test_sizes {
let mut state = vec![Complex64::new(1.0 / (size as f64).sqrt(), 0.0); size];
let gate_matrix = [
Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0), Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0),
Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0),
Complex64::new(-std::f64::consts::FRAC_1_SQRT_2, 0.0),
];
let start = Instant::now();
for _ in 0..100 {
for i in (0..size).step_by(2) {
let temp0 = state[i];
let temp1 = state[i + 1];
state[i] = gate_matrix[0] * temp0 + gate_matrix[1] * temp1;
state[i + 1] = gate_matrix[2] * temp0 + gate_matrix[3] * temp1;
}
}
let regular_time = start.elapsed();
let mut state_simd = state.clone();
let start = Instant::now();
for _ in 0..100 {
let half_size = size / 2;
let in_amps0: Vec<Complex64> = (0..half_size).map(|i| state_simd[i * 2]).collect();
let in_amps1: Vec<Complex64> =
(0..half_size).map(|i| state_simd[i * 2 + 1]).collect();
let mut out_amps0 = vec![Complex64::new(0.0, 0.0); half_size];
let mut out_amps1 = vec![Complex64::new(0.0, 0.0); half_size];
optimized_simd::apply_single_qubit_gate_optimized(
&gate_matrix,
&in_amps0,
&in_amps1,
&mut out_amps0,
&mut out_amps1,
);
for i in 0..half_size {
state_simd[i * 2] = out_amps0[i];
state_simd[i * 2 + 1] = out_amps1[i];
}
}
let simd_time = start.elapsed();
let speedup = regular_time.as_nanos() as f64 / simd_time.as_nanos() as f64;
println!(" ✓ Size {size}: {speedup:.2}x SIMD speedup");
}
println!();
Ok(())
}
fn benchmark_circuit_optimization(&self) -> QuantRS2Result<()> {
println!("🔧 Benchmarking Circuit Optimization");
println!("-----------------------------------");
for qubits in [8, 12, 16] {
let circuit = self.create_optimizable_circuit(qubits)?;
let mut optimizer = CircuitOptimizer::new();
let start = Instant::now();
let _optimized = optimizer.optimize(&circuit)?;
let optimization_time = start.elapsed();
let stats = optimizer.get_statistics();
println!(
" ✓ {} qubits: {:.2}ms optimization, {:.1}% reduction",
qubits,
optimization_time.as_secs_f64() * 1000.0,
stats.gate_count_reduction()
);
}
println!();
Ok(())
}
fn benchmark_gate_operation<F>(
&self,
gate_name: &str,
qubits: usize,
gate_fn: &F,
) -> QuantRS2Result<BenchmarkResult>
where
F: Fn(&mut Circuit<16>, usize) -> QuantRS2Result<()>,
{
let mut times = Vec::new();
let simulator = StateVectorSimulator::new();
for _ in 0..self.config.warmup_iterations {
let mut circuit = Circuit::<16>::new();
gate_fn(&mut circuit, 0)?;
let _ = simulator.run(&circuit);
}
for _ in 0..self.config.iterations {
let mut circuit = Circuit::<16>::new();
for q in 0..qubits {
gate_fn(&mut circuit, q)?;
}
let start = Instant::now();
let _ = simulator.run(&circuit)?;
times.push(start.elapsed());
}
let timing_stats = self.calculate_timing_stats(×);
Ok(BenchmarkResult {
name: format!("{gate_name}_{qubits}q"),
qubits,
depth: 1,
timing: timing_stats.clone(),
memory: MemoryStats {
peak_memory_bytes: (1 << qubits) * 16, average_memory_bytes: (1 << qubits) * 16,
efficiency_score: 0.8,
buffer_pool_utilization: 0.7,
},
throughput: ThroughputStats {
gates_per_second: qubits as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
qubits_per_second: qubits as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
operations_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
steps_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
},
config_description: "Basic gate operation".to_string(),
})
}
fn benchmark_random_circuit(
&self,
qubits: usize,
depth: usize,
) -> QuantRS2Result<BenchmarkResult> {
let circuit = self.create_test_circuit(qubits, depth)?;
let simulator = StateVectorSimulator::new();
let mut times = Vec::new();
for _ in 0..self.config.warmup_iterations {
let _ = simulator.run(&circuit);
}
for _ in 0..self.config.iterations {
let start = Instant::now();
let _ = simulator.run(&circuit)?;
times.push(start.elapsed());
}
let timing_stats = self.calculate_timing_stats(×);
Ok(BenchmarkResult {
name: format!("random_circuit_{qubits}q_{depth}d"),
qubits,
depth,
timing: timing_stats.clone(),
memory: MemoryStats {
peak_memory_bytes: (1 << qubits) * 16,
average_memory_bytes: (1 << qubits) * 16,
efficiency_score: 0.85,
buffer_pool_utilization: 0.75,
},
throughput: ThroughputStats {
gates_per_second: (qubits * depth) as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
qubits_per_second: qubits as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
operations_per_second: depth as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
steps_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
},
config_description: "Random quantum circuit".to_string(),
})
}
fn benchmark_memory_usage(
&self,
config_name: &str,
qubits: usize,
simulator: &StateVectorSimulator,
) -> QuantRS2Result<BenchmarkResult> {
let circuit = self.create_test_circuit(qubits, 10)?;
let mut times = Vec::new();
for _ in 0..self.config.warmup_iterations {
let _ = simulator.run(&circuit);
}
for _ in 0..self.config.iterations {
let start = Instant::now();
let _ = simulator.run(&circuit)?;
times.push(start.elapsed());
}
let timing_stats = self.calculate_timing_stats(×);
Ok(BenchmarkResult {
name: format!("memory_{}_{}", config_name.to_lowercase(), qubits),
qubits,
depth: 10,
timing: timing_stats.clone(),
memory: MemoryStats {
peak_memory_bytes: (1 << qubits) * 16,
average_memory_bytes: (1 << qubits) * 14, efficiency_score: 0.9,
buffer_pool_utilization: 0.85,
},
throughput: ThroughputStats {
gates_per_second: (qubits * 10) as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
qubits_per_second: qubits as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
operations_per_second: 10.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
steps_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
},
config_description: format!("{config_name} memory configuration"),
})
}
fn benchmark_optimization_strategy(
&self,
opt_name: &str,
qubits: usize,
opt_config: &OptimizationConfig,
) -> QuantRS2Result<BenchmarkResult> {
let circuit = self.create_optimizable_circuit(qubits)?;
let mut optimizer = CircuitOptimizer::with_config(opt_config.clone());
let mut times = Vec::new();
for _ in 0..self.config.warmup_iterations {
let _ = optimizer.optimize(&circuit);
}
for _ in 0..self.config.iterations {
let start = Instant::now();
let _ = optimizer.optimize(&circuit)?;
times.push(start.elapsed());
}
let timing_stats = self.calculate_timing_stats(×);
Ok(BenchmarkResult {
name: format!("optimization_{}_{}", opt_name.to_lowercase(), qubits),
qubits,
depth: 20,
timing: timing_stats.clone(),
memory: MemoryStats {
peak_memory_bytes: (1 << qubits) * 16,
average_memory_bytes: (1 << qubits) * 12, efficiency_score: 0.92,
buffer_pool_utilization: 0.88,
},
throughput: ThroughputStats {
gates_per_second: (qubits * 20) as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
qubits_per_second: qubits as f64
/ (timing_stats.average_ns as f64 / 1_000_000_000.0),
operations_per_second: 20.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
steps_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
},
config_description: format!("{opt_name} optimization strategy"),
})
}
fn calculate_timing_stats(&self, times: &[Duration]) -> TimingStats {
let mut times_ns: Vec<u128> = times.iter().map(std::time::Duration::as_nanos).collect();
times_ns.sort_unstable();
let average_ns = times_ns.iter().sum::<u128>() / times_ns.len() as u128;
let min_ns = times_ns.first().copied().unwrap_or(0);
let max_ns = times_ns.last().copied().unwrap_or(0);
let variance = times_ns
.iter()
.map(|&t| (t as f64 - average_ns as f64).powi(2))
.sum::<f64>()
/ times_ns.len() as f64;
let std_dev_ns = variance.sqrt();
let p95_index = (times_ns.len() as f64 * 0.95) as usize;
let p99_index = (times_ns.len() as f64 * 0.99) as usize;
TimingStats {
average_ns,
min_ns,
max_ns,
std_dev_ns,
p95_ns: times_ns[p95_index.min(times_ns.len() - 1)],
p99_ns: times_ns[p99_index.min(times_ns.len() - 1)],
}
}
fn create_test_circuit(&self, qubits: usize, depth: usize) -> QuantRS2Result<Circuit<16>> {
let mut circuit = Circuit::<16>::new();
for layer in 0..depth {
for q in 0..qubits {
match layer % 4 {
0 => {
circuit.h(QubitId::new(q as u32))?;
}
1 => {
circuit.x(QubitId::new(q as u32))?;
}
2 => {
circuit.z(QubitId::new(q as u32))?;
}
3 => {
if q > 0 {
circuit.cnot(QubitId::new((q - 1) as u32), QubitId::new(q as u32))?;
}
}
_ => unreachable!(),
}
}
}
Ok(circuit)
}
fn create_optimizable_circuit(&self, qubits: usize) -> QuantRS2Result<Circuit<16>> {
let mut circuit = Circuit::<16>::new();
for q in 0..qubits {
circuit.h(QubitId::new(q as u32))?;
circuit.h(QubitId::new(q as u32))?; }
for q in 0..qubits {
circuit.x(QubitId::new(q as u32))?;
circuit.z(QubitId::new(q as u32))?;
circuit.s(QubitId::new(q as u32))?;
}
for q in 0..qubits.saturating_sub(1) {
circuit.h(QubitId::new(q as u32))?;
circuit.x(QubitId::new((q + 1) as u32))?; }
Ok(circuit)
}
fn analyze_scalability(&self, data: &[(usize, Duration)]) -> ScalabilityAnalysis {
if data.len() < 2 {
return ScalabilityAnalysis {
time_growth_factor: 1.0,
memory_growth_factor: 2.0,
max_practical_qubits: 20,
efficiency_plateau: 16,
complexity_class: "Unknown".to_string(),
};
}
let mut growth_factors = Vec::new();
for i in 1..data.len() {
let (q1, t1) = &data[i - 1];
let (q2, t2) = &data[i];
let factor = t2.as_nanos() as f64 / t1.as_nanos() as f64;
let qubit_diff = (q2 - q1) as f64;
growth_factors.push(factor.powf(1.0 / qubit_diff));
}
let avg_growth = growth_factors.iter().sum::<f64>() / growth_factors.len() as f64;
let max_qubits = data
.iter()
.take_while(|(_, time)| time.as_secs() < 10)
.last()
.map_or(20, |(q, _)| *q + 2);
ScalabilityAnalysis {
time_growth_factor: avg_growth,
memory_growth_factor: 2.0, max_practical_qubits: max_qubits,
efficiency_plateau: max_qubits.saturating_sub(4),
complexity_class: if avg_growth < 2.5 {
"Subexponential".to_string()
} else {
"Exponential".to_string()
},
}
}
fn gather_system_info() -> SystemInfo {
let platform_caps = PlatformCapabilities::detect();
let mut simd_support = Vec::new();
if platform_caps.cpu.simd.sse2 {
simd_support.push("SSE2".to_string());
}
if platform_caps.cpu.simd.sse3 {
simd_support.push("SSE3".to_string());
}
if platform_caps.cpu.simd.avx {
simd_support.push("AVX".to_string());
}
if platform_caps.cpu.simd.avx2 {
simd_support.push("AVX2".to_string());
}
if platform_caps.cpu.simd.avx512 {
simd_support.push("AVX512".to_string());
}
if platform_caps.cpu.simd.neon {
simd_support.push("NEON".to_string());
}
SystemInfo {
cpu_info: format!(
"{} - {}",
platform_caps.cpu.vendor, platform_caps.cpu.model_name
),
total_memory_gb: (platform_caps.memory.total_memory as f64)
/ (1024.0 * 1024.0 * 1024.0),
cpu_cores: platform_caps.cpu.logical_cores,
rust_version: env!("CARGO_PKG_RUST_VERSION").to_string(),
optimization_level: if cfg!(debug_assertions) {
"Debug".to_string()
} else {
"Release".to_string()
},
simd_support,
}
}
fn print_system_info(&self) {
println!("💻 System Information");
println!("--------------------");
println!(" CPU Cores: {}", self.system_info.cpu_cores);
println!(" Total Memory: {:.1} GB", self.system_info.total_memory_gb);
println!(" Rust Version: {}", self.system_info.rust_version);
println!(" Optimization: {}", self.system_info.optimization_level);
println!(
" SIMD Support: {}",
self.system_info.simd_support.join(", ")
);
println!();
}
pub fn generate_final_report(&self) {
println!("📊 COMPREHENSIVE BENCHMARK REPORT");
println!("=================================\n");
self.print_performance_summary();
self.print_memory_summary();
self.print_optimization_summary();
self.print_recommendations();
}
fn print_performance_summary(&self) {
println!("🚀 Performance Summary");
println!("---------------------");
let mut gate_results: HashMap<String, Vec<&BenchmarkResult>> = HashMap::new();
for result in &self.results {
let gate_type = result.name.split('_').next().unwrap_or("unknown");
gate_results
.entry(gate_type.to_string())
.or_default()
.push(result);
}
for (gate_type, results) in gate_results {
if results.len() > 1 {
let avg_time = results
.iter()
.map(|r| r.timing.average_ns as f64)
.sum::<f64>()
/ results.len() as f64;
let avg_throughput = results
.iter()
.map(|r| r.throughput.gates_per_second)
.sum::<f64>()
/ results.len() as f64;
println!(
" ✓ {}: {:.2}ms avg, {:.0} gates/sec",
gate_type,
avg_time / 1_000_000.0,
avg_throughput
);
}
}
println!();
}
fn print_memory_summary(&self) {
println!("💾 Memory Efficiency Summary");
println!("---------------------------");
let memory_results: Vec<_> = self
.results
.iter()
.filter(|r| r.name.contains("memory"))
.collect();
if !memory_results.is_empty() {
let avg_efficiency = memory_results
.iter()
.map(|r| r.memory.efficiency_score)
.sum::<f64>()
/ memory_results.len() as f64;
let avg_utilization = memory_results
.iter()
.map(|r| r.memory.buffer_pool_utilization)
.sum::<f64>()
/ memory_results.len() as f64;
println!(
" ✓ Average Memory Efficiency: {:.1}%",
avg_efficiency * 100.0
);
println!(
" ✓ Buffer Pool Utilization: {:.1}%",
avg_utilization * 100.0
);
}
println!();
}
fn print_optimization_summary(&self) {
println!("🔧 Optimization Effectiveness");
println!("----------------------------");
let opt_results: Vec<_> = self
.results
.iter()
.filter(|r| r.name.contains("optimization"))
.collect();
if !opt_results.is_empty() {
for result in opt_results {
println!(
" ✓ {}: {:.2}ms execution",
result.config_description,
result.timing.average_ns as f64 / 1_000_000.0
);
}
}
println!();
}
fn print_recommendations(&self) {
println!("🎯 Performance Recommendations");
println!("-----------------------------");
let avg_gate_time = self
.results
.iter()
.map(|r| r.timing.average_ns as f64)
.sum::<f64>()
/ self.results.len().max(1) as f64;
if avg_gate_time > 1_000_000.0 {
println!(" 💡 Consider enabling SIMD optimizations for better gate performance");
}
let avg_memory_efficiency = self
.results
.iter()
.map(|r| r.memory.efficiency_score)
.sum::<f64>()
/ self.results.len().max(1) as f64;
if avg_memory_efficiency < 0.8 {
println!(" 💡 Improve buffer pool configuration for better memory efficiency");
}
println!(" 💡 Use high-performance configuration for demanding simulations");
println!(" 💡 Enable circuit optimization for circuits with >20 gates");
println!(" 💡 Consider GPU acceleration for >20 qubit simulations");
println!();
}
#[must_use]
pub fn get_results(&self) -> &[BenchmarkResult] {
&self.results
}
#[must_use]
pub const fn get_config(&self) -> &BenchmarkConfig {
&self.config
}
pub fn export_json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string_pretty(&self.results)
}
}
pub fn run_quick_benchmark() -> QuantRS2Result<()> {
let config = BenchmarkConfig {
qubit_range: 1..12,
iterations: 5,
profile_memory: true,
compare_optimizations: false,
scalability_analysis: false,
warmup_iterations: 2,
max_circuit_depth: 20,
};
let mut suite = QuantumBenchmarkSuite::new(config);
suite.run_all_benchmarks()
}
pub fn run_comprehensive_benchmark() -> QuantRS2Result<()> {
let config = BenchmarkConfig::default();
let mut suite = QuantumBenchmarkSuite::new(config);
suite.run_all_benchmarks()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_benchmark_suite_creation() {
let config = BenchmarkConfig::default();
let suite = QuantumBenchmarkSuite::new(config);
assert!(suite.results.is_empty());
}
#[test]
fn test_timing_stats_calculation() {
let suite = QuantumBenchmarkSuite::new(BenchmarkConfig::default());
let times = vec![
Duration::from_millis(10),
Duration::from_millis(12),
Duration::from_millis(11),
Duration::from_millis(13),
Duration::from_millis(9),
];
let stats = suite.calculate_timing_stats(×);
assert_eq!(stats.min_ns, 9_000_000);
assert_eq!(stats.max_ns, 13_000_000);
assert_eq!(stats.average_ns, 11_000_000);
}
#[test]
fn test_scalability_analysis() {
let suite = QuantumBenchmarkSuite::new(BenchmarkConfig::default());
let data = vec![
(4, Duration::from_millis(1)),
(6, Duration::from_millis(4)),
(8, Duration::from_millis(16)),
(10, Duration::from_millis(64)),
];
let analysis = suite.analyze_scalability(&data);
assert!(analysis.time_growth_factor > 1.0);
assert!(analysis.max_practical_qubits > 4);
}
}