use chrono::Utc;
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use geo::{Coord, LineString};
use tp_lib_core::calculate_train_path;
use tp_lib_core::models::{GnssPosition, NetRelation, Netelement};
use tp_lib_core::path::PathConfig;
fn create_benchmark_network(segment_count: usize) -> (Vec<Netelement>, Vec<NetRelation>) {
let mut netelements = Vec::with_capacity(segment_count);
let mut netrelations = Vec::with_capacity(segment_count - 1);
for i in 0..segment_count {
let start_lat = 50.0 + (i as f64 * 0.001);
let end_lat = start_lat + 0.001;
let lon = 4.0;
let netelement = Netelement {
id: format!("NE_{:04}", i),
geometry: LineString::new(vec![
Coord {
x: lon,
y: start_lat,
},
Coord { x: lon, y: end_lat },
]),
crs: "EPSG:4326".to_string(),
};
netelements.push(netelement);
if i < segment_count - 1 {
let netrelation = NetRelation::new(
format!("NR_{:04}", i),
format!("NE_{:04}", i),
format!("NE_{:04}", i + 1),
1, 0, true,
true,
)
.unwrap();
netrelations.push(netrelation);
}
}
(netelements, netrelations)
}
fn create_gnss_positions(count: usize, spacing_meters: f64) -> Vec<GnssPosition> {
let mut positions = Vec::with_capacity(count);
let timestamp = Utc::now().into();
for i in 0..count {
let lat = 50.0 + (i as f64 * spacing_meters / 111_000.0); let lon = 4.0;
let position = GnssPosition::new(lat, lon, timestamp, "EPSG:4326".to_string()).unwrap();
positions.push(position);
}
positions
}
fn resampling_performance_comparison(c: &mut Criterion) {
let (netelements, netrelations) = create_benchmark_network(1000);
let position_counts = vec![1000, 5000, 10000];
let mut group = c.benchmark_group("resampling_comparison");
for &pos_count in &position_counts {
let gnss_positions = create_gnss_positions(pos_count, 1.0);
group.bench_with_input(
BenchmarkId::new("full_processing", pos_count),
&pos_count,
|b, _| {
b.iter(|| {
let config = PathConfig::default(); let result =
calculate_train_path(&gnss_positions, &netelements, &netrelations, &config);
let _ = black_box(result);
});
},
);
group.bench_with_input(
BenchmarkId::new("resampled_10m", pos_count),
&pos_count,
|b, _| {
b.iter(|| {
let config = PathConfig {
resampling_distance: Some(10.0),
..PathConfig::default()
};
let result =
calculate_train_path(&gnss_positions, &netelements, &netrelations, &config);
let _ = black_box(result);
});
},
);
}
group.finish();
}
fn path_calculation_benchmark(c: &mut Criterion) {
let (netelements, netrelations) = create_benchmark_network(1000);
c.bench_function("path_calc_1k_positions", |b| {
let gnss_positions = create_gnss_positions(1000, 5.0);
let config = PathConfig::default();
b.iter(|| {
let result =
calculate_train_path(&gnss_positions, &netelements, &netrelations, &config);
let _ = black_box(result);
})
});
}
criterion_group!(
benches,
path_calculation_benchmark,
resampling_performance_comparison
);
criterion_main!(benches);