#![allow(clippy::pedantic, reason = "profiling helper")]
use std::hint::black_box;
use geo_types::Coord;
use map_tile_toolkit::TileId;
#[path = "../tests/support/mod.rs"]
mod support;
use support::Cfg;
enum Op {
All,
One,
}
type Case = (Vec<Coord<i32>>, Vec<TileId>);
fn touched_tiles(cfg: &Cfg, poly: &[Coord<i32>]) -> Vec<TileId> {
let mut acc = cfg.all();
acc.add_feature(poly).expect("polyline");
acc.iter_tiles().map(|t| t.tile_id()).collect()
}
#[cfg_attr(feature = "hotpath", hotpath::main)]
fn main() {
let name = std::env::args()
.nth(1)
.expect("usage: profile <name> [iterations]");
let iterations: Option<u64> = std::env::args().nth(2).and_then(|s| s.parse().ok());
if let Some(cfg) = name.strip_prefix("poly-all-") {
profile_polygon(cfg, iterations);
return;
}
let (polylines, cfg, op, default_iters) = resolve(&name);
let iterations = iterations.unwrap_or(default_iters);
let cases: Vec<Case> = polylines
.into_iter()
.map(|poly| {
let tiles = touched_tiles(&cfg, &poly);
(poly, tiles)
})
.collect();
for _ in 0..iterations {
for (poly, tiles) in &cases {
match op {
Op::All => {
let mut acc = cfg.all();
acc.add_feature(black_box(poly)).expect("polyline");
black_box(&acc);
}
Op::One => {
for &tile in tiles {
let mut acc = cfg.one(tile);
acc.add_feature(black_box(poly)).expect("polyline");
black_box(&acc);
}
}
}
}
}
}
fn profile_polygon(cfg: &str, iterations: Option<u64>) {
let (polygon, slicer, default_iters) = if cfg == "huge" {
(support::huge_square(), support::slicer(4096, 64), 30)
} else {
let slicer = support::big_configs()
.into_iter()
.find(|(c, _)| *c == cfg)
.map(|(_, s)| s)
.unwrap_or_else(|| panic!("unknown polygon config `{cfg}`"));
(support::big_polygon(), slicer, 3_000)
};
let mut acc = slicer.poly_all();
for _ in 0..iterations.unwrap_or(default_iters) {
acc.clear();
acc.add_feature(black_box([support::rings(&polygon)]))
.expect("polygon");
black_box(&acc);
}
}
fn polylines_of(geom: &geo_types::Geometry<i32>) -> Vec<Vec<Coord<i32>>> {
support::lines_of(geom)
.into_iter()
.map(<[_]>::to_vec)
.collect()
}
fn resolve(name: &str) -> (Vec<Vec<Coord<i32>>>, Cfg, Op, u64) {
let small = || {
support::load_all_fixtures()
.into_iter()
.flat_map(|(_, polys)| polys)
.collect()
};
match name {
"all" => (small(), support::grid(), Op::All, 2_000_000),
"one" => (small(), support::grid(), Op::One, 2_000_000),
_ => {
let rest = name
.strip_prefix("big-")
.unwrap_or_else(|| panic!("unknown case name: {name}"));
let (op_str, cfg) = rest
.split_once('-')
.unwrap_or_else(|| panic!("unknown case name: {name}"));
let op = match op_str {
"all" => Op::All,
"one" => Op::One,
_ => panic!("unknown case name: {name}"),
};
let slicer = support::big_configs()
.into_iter()
.find(|(c, _)| *c == cfg)
.map(|(_, s)| s)
.unwrap_or_else(|| panic!("unknown big config `{cfg}` in: {name}"));
(polylines_of(&support::big_polyline()), slicer, op, 3_000)
}
}
}