diff --git a/backend/Cargo.lock b/backend/Cargo.lock index f77e7d5..3779b18 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -26,7 +26,7 @@ dependencies = [ "cfg-if", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.7.26", ] [[package]] @@ -119,6 +119,17 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -135,6 +146,7 @@ dependencies = [ "console_error_panic_hook", "console_log", "contour", + "criterion", "csv", "enum-map", "fast_paths", @@ -147,6 +159,8 @@ dependencies = [ "log", "muv-osm", "osm-reader", + "rand", + "rand_xorshift", "rstar", "serde", "serde-wasm-bindgen", @@ -229,6 +243,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.0.94" @@ -260,6 +280,17 @@ dependencies = [ "windows-targets 0.52.0", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags 1.3.2", + "textwrap", + "unicode-width", +] + [[package]] name = "compact-calendar" version = "0.6.18" @@ -335,6 +366,42 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools 0.10.5", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -678,6 +745,17 @@ dependencies = [ "zstd", ] +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.28.1" @@ -703,6 +781,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + [[package]] name = "hash32" version = "0.3.1" @@ -738,6 +822,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.9" @@ -883,6 +976,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.11.0" @@ -1069,7 +1171,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -1088,6 +1190,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "oorandom" +version = "11.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" + [[package]] name = "opening-hours" version = "0.6.18" @@ -1250,6 +1358,43 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "plotters" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" + +[[package]] +name = "plotters-svg" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f" +dependencies = [ + "zerocopy 0.6.6", +] + [[package]] name = "priority-queue" version = "2.0.2" @@ -1330,6 +1475,45 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + [[package]] name = "rayon" version = "1.8.0" @@ -1503,6 +1687,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.23" @@ -1561,6 +1754,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.202" @@ -1732,6 +1935,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.50" @@ -1752,6 +1964,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.6.1" @@ -1892,6 +2114,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + [[package]] name = "url" version = "2.5.2" @@ -1929,6 +2157,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2055,6 +2293,37 @@ dependencies = [ "rustix", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.52.0" @@ -2206,13 +2475,34 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "zerocopy" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" +dependencies = [ + "byteorder", + "zerocopy-derive 0.6.6", +] + [[package]] name = "zerocopy" version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" dependencies = [ - "zerocopy-derive", + "zerocopy-derive 0.7.26", +] + +[[package]] +name = "zerocopy-derive" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 6385500..8680c52 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -44,3 +44,12 @@ tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] } # use dev profile and avoid wasm-opt. [profile.dev.package."*"] opt-level = 3 + +[dev-dependencies] +criterion = { version = "0.3", features = ["html_reports"] } +rand = "0.8.5" +rand_xorshift = "0.3.0" + +[[bench]] +name = "pt_routing" +harness = false diff --git a/backend/benches/pt_routing.rs b/backend/benches/pt_routing.rs new file mode 100644 index 0000000..9287304 --- /dev/null +++ b/backend/benches/pt_routing.rs @@ -0,0 +1,49 @@ +use backend::{MapModel, RouteRequest}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; + +pub fn criterion_benchmark(c: &mut Criterion) { + // cargo run --release graph ~/cloudflare_sync/severance_pbfs/elephant_castle.pbf ~/Downloads/uk_gtfs/ + let bytes = std::fs::read("graph.bin").unwrap(); + let map = MapModel::from_graph_bytes(&bytes).unwrap(); + + // Fixed seed for determinism + let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(42); + let bounds = map.get_bounds(); + + let mut group = c.benchmark_group("calculate routes"); + // TODO Try just a few inputs, because criterion repeats each input so many times + for case in 0..3 { + let (x1, y1) = rand_pt(&mut rng, &bounds); + let (x2, y2) = rand_pt(&mut rng, &bounds); + let req = RouteRequest { + x1, + y1, + x2, + y2, + mode: "transit".to_string(), + debug_search: false, + use_heuristic: true, + start_time: "07:00".to_string(), + }; + + group.bench_with_input( + BenchmarkId::new("calculate routes", case), + &req, + |b, input| b.iter(|| map.route_from_req(input)), + ); + } + group.finish(); +} + +// TODO Or get the boundary polygon and ensure it's inside there +fn rand_pt(rng: &mut XorShiftRng, bounds: &Vec) -> (f64, f64) { + ( + rng.gen_range(bounds[0]..bounds[2]), + rng.gen_range(bounds[1]..bounds[3]), + ) +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 72ea426..f376edf 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -120,10 +120,39 @@ impl MapModel { .map_err(err_to_js) } - // mut because of path_calc #[wasm_bindgen(js_name = route)] pub fn route(&self, input: JsValue) -> Result { let req: RouteRequest = serde_wasm_bindgen::from_value(input)?; + self.route_from_req(&req) + } + + #[wasm_bindgen(js_name = score)] + pub fn score( + &self, + input: JsValue, + progress_cb: Option, + ) -> Result { + let req: ScoreRequest = serde_wasm_bindgen::from_value(input)?; + let poi_kinds: HashSet = req.poi_kinds.into_iter().collect(); + let limit = Duration::from_secs(req.max_seconds); + score::calculate( + &self.graph, + poi_kinds, + limit, + Timer::new("score", progress_cb), + ) + .map_err(err_to_js) + } +} + +// Non WASM methods +impl MapModel { + pub fn from_graph_bytes(input_bytes: &[u8]) -> Result { + let graph = bincode::deserialize_from(input_bytes).map_err(err_to_js)?; + Ok(MapModel { graph }) + } + + pub fn route_from_req(&self, req: &RouteRequest) -> Result { let mode = match req.mode.as_str() { "car" => Mode::Car, "bicycle" => Mode::Bicycle, @@ -165,24 +194,6 @@ impl MapModel { .map_err(err_to_js) } } - - #[wasm_bindgen(js_name = score)] - pub fn score( - &self, - input: JsValue, - progress_cb: Option, - ) -> Result { - let req: ScoreRequest = serde_wasm_bindgen::from_value(input)?; - let poi_kinds: HashSet = req.poi_kinds.into_iter().collect(); - let limit = Duration::from_secs(req.max_seconds); - score::calculate( - &self.graph, - poi_kinds, - limit, - Timer::new("score", progress_cb), - ) - .map_err(err_to_js) - } } #[derive(Deserialize)] @@ -196,15 +207,15 @@ pub struct IsochroneRequest { #[derive(Deserialize)] pub struct RouteRequest { - x1: f64, - y1: f64, - x2: f64, - y2: f64, - mode: String, + pub x1: f64, + pub y1: f64, + pub x2: f64, + pub y2: f64, + pub mode: String, // TODO Only works for transit - debug_search: bool, - use_heuristic: bool, - start_time: String, + pub debug_search: bool, + pub use_heuristic: bool, + pub start_time: String, } #[derive(Deserialize)]