Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v0.7.0: rework features, tile_id perf (#31)
* optimize `tile_id` to compute base 15-22x faster * use the same features approach as reqwest - introduce "hidden" features to simplify conditional compilation * use `just fmt` to clean up some formatting * slightly shorter vars in a few places * sort mods first, uses second in the lib.rs * move all backends into simple files because this way we can incrementally append new functions to the base reader without any conditionals - each backend file defines its own * add a few `reqwest` crate features to simplify their enablement * reexport `tilejson` crate # tile_id perf optimization I ran criterion benchmarks for zoom 28 and zoom 12. The hardcoded table values only has 0..20 zooms. Note that this is only base computation, not the hilbert part. For z28, the performance is 15x better (77.1ns -> 5.3ns) For z12, the performance is 22x better (24.523ns -> 1.1221ns) ``` tile_id_original_28 time: [76.980 ns 77.155 ns 77.386 ns] Found 11 outliers among 100 measurements (11.00%) 1 (1.00%) high mild 10 (10.00%) high severe tile_id_original_12 time: [24.518 ns 24.523 ns 24.529 ns] Found 16 outliers among 100 measurements (16.00%) 9 (9.00%) high mild 7 (7.00%) high severe tile_id_new time: [5.3056 ns 5.3072 ns 5.3094 ns] change: [-0.4333% -0.1397% +0.0256%] (p = 0.38 > 0.05) No change in performance detected. Found 8 outliers among 100 measurements (8.00%) 1 (1.00%) low mild 4 (4.00%) high mild 3 (3.00%) high severe tile_id_new_12 time: [1.1171 ns 1.1221 ns 1.1313 ns] Found 13 outliers among 100 measurements (13.00%) 6 (6.00%) high mild 7 (7.00%) high severe ``` <details><summary>Benchmarking code</summary> <p> add these lines right after the `[dependencies]` section: ```toml criterion = "0.5.1" [[bench]] name = "tile_id" harness = false ``` Create a new file `benches/tile_id.rs`: ```rust #![allow(clippy::unreadable_literal)] use criterion::{black_box, criterion_group, criterion_main, Criterion}; const PYRAMID_SIZE_BY_ZOOM: [u64; 21] = [ /* 0 */ 0, /* 1 */ 1, /* 2 */ 5, /* 3 */ 21, /* 4 */ 85, /* 5 */ 341, /* 6 */ 1365, /* 7 */ 5461, /* 8 */ 21845, /* 9 */ 87381, /* 10 */ 349525, /* 11 */ 1398101, /* 12 */ 5592405, /* 13 */ 22369621, /* 14 */ 89478485, /* 15 */ 357913941, /* 16 */ 1431655765, /* 17 */ 5726623061, /* 18 */ 22906492245, /* 19 */ 91625968981, /* 20 */ 366503875925, ]; pub fn tile_id_new(z: u8) -> u64 { // The 0/0/0 case is not needed for the base id computation, but it will fail hilbert_2d::u64::xy2h_discrete if z == 0 { return 0; } let z_ind = usize::from(z); let base_id = if z_ind < PYRAMID_SIZE_BY_ZOOM.len() { PYRAMID_SIZE_BY_ZOOM[z_ind] } else { let last_ind = PYRAMID_SIZE_BY_ZOOM.len() - 1; PYRAMID_SIZE_BY_ZOOM[last_ind] + (last_ind..z_ind).map(|i| 1_u64 << (i << 1)).sum::<u64>() }; base_id } pub fn tile_id_original(z: u8) -> u64 { if z == 0 { return 0; } // TODO: minor optimization with bit shifting let base_id: u64 = 1 + (1..z).map(|i| 4u64.pow(u32::from(i))).sum::<u64>(); base_id } fn bench_original(c: &mut Criterion) { c.bench_function("tile_id_original_28", |b| { b.iter(|| { assert_eq!(tile_id_original(black_box(28)), 24019198012642645); }) }); c.bench_function("tile_id_original_12", |b| { b.iter(|| { assert_eq!(tile_id_original(black_box(12)), 5592405); }) }); } fn bench_new(c: &mut Criterion) { c.bench_function("tile_id_new", |b| { b.iter(|| { assert_eq!(tile_id_new(black_box(28)), 24019198012642645); }) }); c.bench_function("tile_id_new_12", |b| { b.iter(|| { assert_eq!(tile_id_new(black_box(12)), 5592405); }) }); } criterion_group!(benches, bench_original, bench_new); criterion_main!(benches); ``` </p> </details>
- Loading branch information