use ruviz::core::*;
use ruviz::data::*;
use ruviz::render::gpu::{GpuRenderer, initialize_gpu_backend};
use ruviz::render::pooled::PooledRenderer;
use std::time::Instant;
#[tokio::main]
async fn main() -> Result<()> {
println!("📊 GPU vs CPU Scaling Test");
println!("===========================\n");
let cpu_renderer = PooledRenderer::new();
println!("✅ CPU Renderer ready");
let mut gpu_renderer = match initialize_gpu_backend().await {
Ok(_) => match GpuRenderer::new().await {
Ok(renderer) => {
println!(
"✅ GPU Renderer ready - threshold: {}",
renderer.gpu_threshold()
);
Some(renderer)
}
Err(e) => {
println!("⚠️ GPU failed: {}", e);
None
}
},
Err(e) => {
println!("⚠️ GPU backend failed: {}", e);
None
}
};
let test_sizes = vec![1_000, 5_000, 10_000, 50_000, 100_000, 500_000];
println!(
"\n{:>10} {:>15} {:>15} {:>10}",
"Points", "CPU (ms)", "GPU (ms)", "Speedup"
);
println!("{}", "-".repeat(60));
for &point_count in &test_sizes {
let x_data: Vec<f64> = (0..point_count).map(|i| i as f64 * 0.01).collect();
let y_data: Vec<f64> = x_data.iter().map(|&x| (x * 0.5).sin()).collect();
let x_range = (0.0, x_data[x_data.len() - 1]);
let y_range = (-1.0, 1.0);
let viewport = (0.0, 0.0, 1920.0, 1080.0);
let start = Instant::now();
let _cpu_result = cpu_renderer.transform_coordinates_pooled(
&x_data, &y_data, x_range.0, x_range.1, y_range.0, y_range.1, viewport.0, viewport.1,
viewport.2, viewport.3,
)?;
let cpu_time = start.elapsed();
let (gpu_time, speedup) = if let Some(ref mut gpu) = gpu_renderer {
let start = Instant::now();
match gpu.transform_coordinates_optimal(&x_data, &y_data, x_range, y_range, viewport) {
Ok(_) => {
let gpu_time = start.elapsed();
let speedup = cpu_time.as_secs_f64() / gpu_time.as_secs_f64();
(gpu_time, speedup)
}
Err(_) => (cpu_time, 1.0), }
} else {
(cpu_time, 1.0)
};
println!(
"{:>10} {:>12.1} {:>12.1} {:>9.1}x",
format_number(point_count as u64),
cpu_time.as_millis() as f64,
gpu_time.as_millis() as f64,
speedup
);
if cpu_time.as_secs_f64() > 2.0 {
println!("CPU time > 2s, stopping here");
break;
}
}
if let Some(gpu) = &gpu_renderer {
let stats = gpu.get_stats();
println!("\n📈 GPU Statistics:");
println!("GPU operations: {}", stats.gpu_operations);
println!("CPU operations: {}", stats.cpu_operations);
println!(
"Total GPU points: {}",
format_number(stats.gpu_points_processed)
);
println!(
"Total CPU points: {}",
format_number(stats.cpu_points_processed)
);
}
Ok(())
}
fn format_number(n: u64) -> String {
let s = n.to_string();
let chars: Vec<char> = s.chars().collect();
let mut result = String::new();
for (i, &ch) in chars.iter().enumerate() {
if i > 0 && (chars.len() - i).is_multiple_of(3) {
result.push(',');
}
result.push(ch);
}
result
}