use ruviz::prelude::*;
use std::time::Instant;
fn main() -> Result<()> {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("failed to create current-thread Tokio runtime for interactive example")
.block_on(async_main())
}
async fn async_main() -> Result<()> {
println!("Starting real-time performance demo...");
println!("Controls:");
println!(" - Mouse wheel: Zoom in/out");
println!(" - Left click + drag: Pan");
println!(" - Right click: Context menu");
println!(" - Right click + drag: Box zoom");
println!(" - Escape: Reset view");
println!(" - Cmd/Ctrl+S: Save PNG");
println!(" - Cmd/Ctrl+C: Copy image");
println!(" - Close window to exit");
std::fs::create_dir_all("generated/examples").ok();
let initial_size = 100_000;
let dataset = generate_large_dataset(initial_size);
println!(
"Generated {} points in {:.2}ms ({:.2}MB)",
dataset.size, dataset.generation_time_ms, dataset.memory_usage_mb
);
let plot: Plot = Plot::new()
.title(format!("Large Dataset Explorer - {} points", initial_size))
.xlabel("Time (s)")
.ylabel("Signal Amplitude")
.legend(Position::TopLeft)
.line(&dataset.x_data, &dataset.y_data)
.into();
#[cfg(feature = "interactive")]
{
println!("Opening performance demo window...");
show_interactive(plot).await?;
}
#[cfg(not(feature = "interactive"))]
{
println!("Interactive features not enabled.");
println!("To enable: cargo run --features interactive --example real_time_performance");
run_static_performance_benchmark(&dataset)?;
plot.save("generated/examples/real_time_performance_static.png")?;
println!("Saved: generated/examples/real_time_performance_static.png");
}
Ok(())
}
#[allow(dead_code)]
struct PerformanceDataset {
x_data: Vec<f64>,
y_data: Vec<f64>,
size: usize,
generation_time_ms: f64,
memory_usage_mb: f64,
}
fn generate_large_dataset(n_points: usize) -> PerformanceDataset {
let start_time = Instant::now();
let mut x_data = Vec::with_capacity(n_points);
let mut y_data = Vec::with_capacity(n_points);
for i in 0..n_points {
let t = i as f64 * 0.001;
x_data.push(t);
let signal = (t * 2.0 * std::f64::consts::PI * 1.0).sin() * 1.0
+ (t * 2.0 * std::f64::consts::PI * 3.0).sin() * 0.5
+ (t * 2.0 * std::f64::consts::PI * 10.0).sin() * 0.2
+ (t * 2.0 * std::f64::consts::PI * 50.0).sin() * 0.1
+ (i as f64 * 0.00001).sin() * 0.05;
y_data.push(signal);
}
let generation_time = start_time.elapsed();
let memory_usage = (x_data.len() + y_data.len()) * std::mem::size_of::<f64>();
PerformanceDataset {
x_data,
y_data,
size: n_points,
generation_time_ms: generation_time.as_secs_f64() * 1000.0,
memory_usage_mb: memory_usage as f64 / 1_048_576.0,
}
}
#[allow(dead_code)]
fn run_static_performance_benchmark(dataset: &PerformanceDataset) -> Result<()> {
println!("\nRunning static rendering benchmark...");
let plot: Plot = Plot::new()
.title(format!("Performance Benchmark - {} points", dataset.size))
.line(&dataset.x_data, &dataset.y_data)
.into();
let render_start = Instant::now();
plot.save("generated/examples/benchmark_output.png")?;
let render_time = render_start.elapsed();
println!("Benchmark Results:");
println!(" Dataset size: {} points", dataset.size);
println!(" Memory usage: {:.2}MB", dataset.memory_usage_mb);
println!(" Render time: {:.2}ms", render_time.as_secs_f64() * 1000.0);
println!(
" Points/sec: {:.0}",
dataset.size as f64 / render_time.as_secs_f64()
);
let target_fps = 60.0;
let target_frame_time_ms = 1000.0 / target_fps;
let performance_margin = target_frame_time_ms / (render_time.as_secs_f64() * 1000.0);
println!(
" Performance margin: {:.1}x (for 60fps)",
performance_margin
);
std::fs::remove_file("generated/examples/benchmark_output.png").ok();
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dataset_generation() {
let dataset = generate_large_dataset(1000);
assert_eq!(dataset.x_data.len(), 1000);
assert_eq!(dataset.y_data.len(), 1000);
assert!(dataset.generation_time_ms > 0.0);
}
#[test]
fn test_static_benchmark() {
std::fs::create_dir_all("generated/examples").ok();
let dataset = generate_large_dataset(1000);
let result = run_static_performance_benchmark(&dataset);
assert!(result.is_ok());
}
}