diff options
| author | Rutger Broekhoff | 2026-09-08 12:30:06 +0200 |
|---|---|---|
| committer | Rutger Broekhoff | 2026-09-08 12:30:06 +0200 |
| commit | e3e0dc994c6ba244472f58b940d0196616bb84b0 (patch) | |
| tree | 5145e91ff96490158e312068e39123fee945c896 /server | |
| parent | 3fcfe8e5b2c76efeea1e838fb6b7e235804ecd8f (diff) | |
| download | routemon-e3e0dc994c6ba244472f58b940d0196616bb84b0.tar.gz routemon-e3e0dc994c6ba244472f58b940d0196616bb84b0.zip | |
More performance improvements
Diffstat (limited to 'server')
| -rw-r--r-- | server/src/api.cpp | 17 | ||||
| -rw-r--r-- | server/src/api.cppm | 10 | ||||
| -rw-r--r-- | server/src/geo/multizonal.cppm | 63 |
3 files changed, 73 insertions, 17 deletions
diff --git a/server/src/api.cpp b/server/src/api.cpp index 137666b..e35e1b3 100644 --- a/server/src/api.cpp +++ b/server/src/api.cpp | |||
| @@ -95,7 +95,7 @@ auto tag_invoke(json::value_from_tag, json::value& jv, sysinfo const& info) | |||
| 95 | {"using_publication_of", | 95 | {"using_publication_of", |
| 96 | std::format("{:%FT%TZ}", info.using_publication_of)}, | 96 | std::format("{:%FT%TZ}", info.using_publication_of)}, |
| 97 | {"blse_index_size", info.blse_index_size}, | 97 | {"blse_index_size", info.blse_index_size}, |
| 98 | {"p_index_size", info.p_index_size}, | 98 | {"bpe_index_size", info.bpe_index_size}, |
| 99 | }; | 99 | }; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| @@ -124,7 +124,7 @@ handler::handler(log::logger const& l, datex2::situation_publication pub) | |||
| 124 | } | 124 | } |
| 125 | for (auto p : rc->relevant_points) | 125 | for (auto p : rc->relevant_points) |
| 126 | { | 126 | { |
| 127 | p_index_.insert(p_index_value{p, rc}); | 127 | bpe_index_.insert(p, rc); |
| 128 | } | 128 | } |
| 129 | } | 129 | } |
| 130 | 130 | ||
| @@ -141,7 +141,7 @@ handler::handler(log::logger const& l, datex2::situation_publication pub) | |||
| 141 | auto const dur_build_s = chrono::duration<double>{after_build - before_build}; | 141 | auto const dur_build_s = chrono::duration<double>{after_build - before_build}; |
| 142 | l_.info("Indexes built in {}", dur_build_s); | 142 | l_.info("Indexes built in {}", dur_build_s); |
| 143 | l_.info("BLSE index size: {}", blse_index_.size()); | 143 | l_.info("BLSE index size: {}", blse_index_.size()); |
| 144 | l_.info("Point index size: {}", p_index_.size()); | 144 | l_.info("Point index size: {}", bpe_index_.size()); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | auto handler::process_gpx(gpx::file&& gpx_file) | 147 | auto handler::process_gpx(gpx::file&& gpx_file) |
| @@ -194,17 +194,12 @@ auto handler::process_gpx(gpx::file&& gpx_file) | |||
| 194 | // relevant_road_closures.emplace(rc); | 194 | // relevant_road_closures.emplace(rc); |
| 195 | ls_checked++; | 195 | ls_checked++; |
| 196 | } | 196 | } |
| 197 | for (auto it = p_index_.qbegin(bgeo::index::intersects(part_box)); | 197 | for (auto const& rc : bpe_index_.intersection(part_zone_lss)) |
| 198 | it != p_index_.qend(); it++) | ||
| 199 | { | 198 | { |
| 200 | // Cannot use structured bindings here for the same reason as above. | ||
| 201 | geo::utm::zonable_wgs84_point const& p = std::get<0>(*it); | ||
| 202 | std::shared_ptr<datex2::road_closure> const& rc = std::get<1>(*it); | ||
| 203 | if (rc->validity | 199 | if (rc->validity |
| 204 | && rc->validity->intersect(check_periods).periods().empty()) | 200 | && rc->validity->intersect(check_periods).periods().empty()) |
| 205 | continue; | 201 | continue; |
| 206 | if (bgeo::distance(p, part, vincenty_strategy) < min_distance_) | 202 | relevant_road_closures.emplace(rc); |
| 207 | relevant_road_closures.emplace(rc); | ||
| 208 | p_checked++; | 203 | p_checked++; |
| 209 | } | 204 | } |
| 210 | } | 205 | } |
| @@ -285,7 +280,7 @@ auto handler::sysinfo() -> struct sysinfo | |||
| 285 | return { | 280 | return { |
| 286 | .using_publication_of = pub_.publication_time, | 281 | .using_publication_of = pub_.publication_time, |
| 287 | .blse_index_size = blse_index_.size(), | 282 | .blse_index_size = blse_index_.size(), |
| 288 | .p_index_size = p_index_.size(), | 283 | .bpe_index_size = bpe_index_.size(), |
| 289 | }; | 284 | }; |
| 290 | } | 285 | } |
| 291 | 286 | ||
diff --git a/server/src/api.cppm b/server/src/api.cppm index 77e0f85..0bb0868 100644 --- a/server/src/api.cppm +++ b/server/src/api.cppm | |||
| @@ -57,7 +57,7 @@ struct sysinfo | |||
| 57 | { | 57 | { |
| 58 | time::timestamp using_publication_of; | 58 | time::timestamp using_publication_of; |
| 59 | std::size_t blse_index_size; | 59 | std::size_t blse_index_size; |
| 60 | std::size_t p_index_size; | 60 | std::size_t bpe_index_size; |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | auto tag_invoke( | 63 | auto tag_invoke( |
| @@ -82,15 +82,13 @@ class handler | |||
| 82 | 82 | ||
| 83 | using blse_index_value = std::shared_ptr<datex2::road_closure>; | 83 | using blse_index_value = std::shared_ptr<datex2::road_closure>; |
| 84 | using blse_index = geo::multizonal::linestring_rtree<blse_index_value>; | 84 | using blse_index = geo::multizonal::linestring_rtree<blse_index_value>; |
| 85 | using p_index_value = std::pair< | 85 | using bpe_index_value = std::shared_ptr<datex2::road_closure>; |
| 86 | geo::utm::zonable_wgs84_point, std::shared_ptr<datex2::road_closure> | 86 | using bpe_index = geo::multizonal::point_rtree<bpe_index_value>; |
| 87 | >; | ||
| 88 | using p_index = bgeo::index::rtree<p_index_value, bgeo::index::quadratic<16>>; | ||
| 89 | 87 | ||
| 90 | log::logger l_; | 88 | log::logger l_; |
| 91 | datex2::situation_publication pub_; | 89 | datex2::situation_publication pub_; |
| 92 | blse_index blse_index_; | 90 | blse_index blse_index_; |
| 93 | p_index p_index_; | 91 | bpe_index bpe_index_; |
| 94 | 92 | ||
| 95 | public: | 93 | public: |
| 96 | explicit handler(log::logger const& l, datex2::situation_publication pub); | 94 | explicit handler(log::logger const& l, datex2::situation_publication pub); |
diff --git a/server/src/geo/multizonal.cppm b/server/src/geo/multizonal.cppm index ed78a24..7930367 100644 --- a/server/src/geo/multizonal.cppm +++ b/server/src/geo/multizonal.cppm | |||
| @@ -241,4 +241,67 @@ public: | |||
| 241 | } | 241 | } |
| 242 | }; | 242 | }; |
| 243 | 243 | ||
| 244 | template<class T> | ||
| 245 | class point_rtree | ||
| 246 | { | ||
| 247 | public: | ||
| 248 | using index_value = std::tuple<utm::zone_local::prim::box, utm::zone_local::prim::point, T>; | ||
| 249 | |||
| 250 | private: | ||
| 251 | multi_zone<bgeo::index::rtree<index_value, bgeo::index::quadratic<16>>> local_rtrees_; | ||
| 252 | |||
| 253 | public: | ||
| 254 | template<std::convertible_to<T> U> | ||
| 255 | auto insert(utm::zonable_wgs84_point const& p, U&& arg) -> void | ||
| 256 | { | ||
| 257 | auto to_utm = wgs84::utm_transforms::instance(); | ||
| 258 | |||
| 259 | auto p_zone = utm::zone::for_wgs84_point(p); | ||
| 260 | auto mp_alt_zone = std::optional<utm::zone>{}; | ||
| 261 | if (auto [neighbor_zone, neighbor_zone_dist] = wgs84::neighbor_utm_zone(p); | ||
| 262 | neighbor_zone_dist < 30.0 /* m */) | ||
| 263 | mp_alt_zone = neighbor_zone; | ||
| 264 | |||
| 265 | auto insert = [&](utm::zone z) -> void | ||
| 266 | { | ||
| 267 | auto p_utm = to_utm[z].apply(p); | ||
| 268 | auto bpe = bgeo::return_buffer<utm::zone_local::prim::box>(bgeo::return_envelope<utm::zone_local::prim::box>(p_utm), 30.0 /* m */); | ||
| 269 | local_rtrees_[z].insert(index_value{bpe, p_utm, arg}); | ||
| 270 | }; | ||
| 271 | |||
| 272 | insert(p_zone); | ||
| 273 | if (mp_alt_zone) | ||
| 274 | insert(*mp_alt_zone); | ||
| 275 | } | ||
| 276 | |||
| 277 | auto size() const -> std::size_t | ||
| 278 | { | ||
| 279 | auto total_size = 0uz; | ||
| 280 | for (auto z = utm::zone::min(); z != utm::zone::max(); z = z.next()) | ||
| 281 | total_size += local_rtrees_[z].size(); | ||
| 282 | return total_size; | ||
| 283 | } | ||
| 284 | |||
| 285 | // Note: the same T may be generated more than once! | ||
| 286 | auto intersection(zoned_linestring_seg_seq const& lss) const -> std::generator<T const&> | ||
| 287 | { | ||
| 288 | for (auto const& ls : lss.segments) | ||
| 289 | { | ||
| 290 | // auto ls_box = bgeo::return_envelope<utm::zone_local::prim::box>(ls); | ||
| 291 | for (auto it = local_rtrees_[ls.zone].qbegin(bgeo::index::intersects(ls)); | ||
| 292 | it != local_rtrees_[ls.zone].qend(); it++) | ||
| 293 | { | ||
| 294 | using multi_linestring = bgeo::model::multi_linestring<utm::zone_local::prim::linestring>; | ||
| 295 | |||
| 296 | auto relevant_ls_parts = multi_linestring{}; | ||
| 297 | bgeo::intersection(std::get<0>(*it), static_cast<utm::zone_local::prim::linestring const&>(ls), relevant_ls_parts); | ||
| 298 | if (bgeo::distance(relevant_ls_parts, std::get<1>(*it)) < 30.0 /* m */) | ||
| 299 | { | ||
| 300 | co_yield std::get<2>(*it); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | } | ||
| 304 | } | ||
| 305 | }; | ||
| 306 | |||
| 244 | } // namespace routemon::geo::multizonal | 307 | } // namespace routemon::geo::multizonal |