benchmark/
benchmark.rs

1//! Exemplo de benchmark de performance
2//! Compara FFT recursiva vs iterativa
3
4use avila_fft::{Complex, FftPlanner, fft};
5use std::time::Instant;
6
7fn benchmark_recursive(size: usize, iterations: usize) -> f64 {
8    let input: Vec<Complex<f64>> = (0..size)
9        .map(|i| Complex::new((i as f64).sin(), (i as f64).cos()))
10        .collect();
11
12    let start = Instant::now();
13    for _ in 0..iterations {
14        let _ = fft(&input);
15    }
16    let duration = start.elapsed();
17    duration.as_secs_f64() / (iterations as f64)
18}
19
20fn benchmark_iterative(size: usize, iterations: usize) -> f64 {
21    let input: Vec<Complex<f64>> = (0..size)
22        .map(|i| Complex::new((i as f64).sin(), (i as f64).cos()))
23        .collect();
24
25    let planner = FftPlanner::new(size, false).unwrap();
26
27    let start = Instant::now();
28    for _ in 0..iterations {
29        let _ = planner.process(&input).unwrap();
30    }
31    let duration = start.elapsed();
32    duration.as_secs_f64() / (iterations as f64)
33}
34
35fn main() {
36    println!("=== Benchmark FFT - Avila FFT ===");
37    println!("Compile com --release para resultados precisos!\n");
38
39    let sizes = vec![64, 128, 256, 512, 1024, 2048, 4096];
40
41    println!("{:>6} | {:>12} | {:>12} | {:>10} | {:>12}",
42        "N", "Recursiva", "Iterativa", "Speedup", "Throughput");
43    println!("{}", "-".repeat(70));
44
45    for &size in &sizes {
46        // Mais iterações para tamanhos menores
47        let iterations = (100000 / size).max(10);
48
49        let time_recursive = benchmark_recursive(size, iterations);
50        let time_iterative = benchmark_iterative(size, iterations);
51        let speedup = time_recursive / time_iterative;
52        let throughput = (size as f64) / time_iterative / 1e6; // Msamples/s
53
54        println!("{:6} | {:9.2} µs | {:9.2} µs | {:8.2}x | {:8.1} Ms/s",
55            size,
56            time_recursive * 1e6,
57            time_iterative * 1e6,
58            speedup,
59            throughput
60        );
61    }
62
63    println!("\n=== Análise de Complexidade ===\n");
64
65    // Verifica se segue O(N log N)
66    println!("Verificando complexidade O(N log N):");
67    let base_size = 256;
68    let base_time = benchmark_iterative(base_size, 1000);
69
70    for &size in &[512, 1024, 2048] {
71        let time = benchmark_iterative(size, 1000);
72        let ratio = size / base_size;
73        let expected_ratio = (ratio as f64) * (size as f64).log2() / (base_size as f64).log2();
74        let actual_ratio = time / base_time;
75
76        println!("  N={:4}: esperado {:.2}x, observado {:.2}x",
77            size, expected_ratio, actual_ratio);
78    }
79
80    println!("\n=== Teste de Precisão ===\n");
81
82    // Compara precisão entre recursiva e iterativa
83    let test_size = 1024;
84    let input: Vec<Complex<f64>> = (0..test_size)
85        .map(|i| Complex::new((i as f64) * 0.1, (i as f64) * 0.05))
86        .collect();
87
88    let result_recursive = fft(&input);
89
90    let planner = FftPlanner::new(test_size, false).unwrap();
91    let result_iterative = planner.process(&input).unwrap();
92
93    let max_error = result_recursive.iter()
94        .zip(result_iterative.iter())
95        .map(|(a, b)| (a.re - b.re).abs().max((a.im - b.im).abs()))
96        .fold(0.0, f64::max);
97
98    println!("Erro máximo entre recursiva e iterativa: {:.2e}", max_error);
99
100    if max_error < 1e-10 {
101        println!("✓ Precisão idêntica!");
102    } else {
103        println!("⚠ Diferença detectada (ainda aceitável)");
104    }
105
106    println!("\n=== Uso de Memória ===\n");
107
108    println!("Recursiva:");
109    println!("  - Cria O(N log N) vetores temporários");
110    println!("  - Stack frames: O(log N)");
111    println!("  - Não recomendada para N grande\n");
112
113    println!("Iterativa:");
114    println!("  - Trabalha in-place após bit-reversal");
115    println!("  - Cache de twiddle factors: O(N/2)");
116    println!("  - Recomendada para produção");
117}