From ae652cab3cf0541173b31273bcec5746a9a81e68 Mon Sep 17 00:00:00 2001 From: Rutger Broekhoff Date: Fri, 11 Sep 2026 17:22:44 +0200 Subject: Speed improvements --- server/src/geo/utm.cppm | 44 +++++++++++++++++----------- server/src/log.cpp | 30 ++++++++----------- server/src/log.cppm | 10 +------ server/src/srv.cpp | 8 ++--- server/src/trace.cpp | 77 ++++++++++++++++++++++++++++++++----------------- server/src/trace.cppm | 6 ++-- 6 files changed, 98 insertions(+), 77 deletions(-) diff --git a/server/src/geo/utm.cppm b/server/src/geo/utm.cppm index c58ffb4..75bba6f 100644 --- a/server/src/geo/utm.cppm +++ b/server/src/geo/utm.cppm @@ -110,6 +110,7 @@ using zonable_wgs84_linestring = // and easting (so no Norway/Svalbard exceptions). class zone { +public: // Note: calculations heavily depend on the values of the variants. enum class hemisphere : std::uint8_t { @@ -117,23 +118,6 @@ class zone southern = 1, }; - // Negative if in the southern hemisphere - // Equal to (zone_no - 1) * 2 + hemisphere - // In range [0, 119] - std::uint8_t zone_; - - static constexpr auto zone_no_valid(std::uint8_t zone_no) -> bool - { - return 0 < zone_no && zone_no <= 60; - } - - static constexpr auto from(std::uint8_t zone_no, hemisphere h) -> std::uint8_t - { - if (!zone_no_valid(zone_no)) - throw std::invalid_argument{"invalid UTM zone number"}; - return (zone_no - 1) * 2 + static_cast(h); - } - public: explicit constexpr zone(std::uint8_t zone_no, hemisphere h) : zone_{from(zone_no, h)} @@ -196,8 +180,34 @@ public: { return zone_ == rhs.zone_; } + +private: + static constexpr auto zone_no_valid(std::uint8_t zone_no) -> bool + { + return 0 < zone_no && zone_no <= 60; + } + + static constexpr auto from(std::uint8_t zone_no, enum hemisphere h) + -> std::uint8_t + { + if (!zone_no_valid(zone_no)) + throw std::invalid_argument{"invalid UTM zone number"}; + return (zone_no - 1) * 2 + static_cast(h); + } + + // Negative if in the southern hemisphere + // Equal to (zone_no - 1) * 2 + hemisphere + // In range [0, 119] + std::uint8_t zone_; }; static_assert(zone::min().as_index() == 0); static_assert(zone::max().as_index() == 119); +auto to_string(zone z) -> std::string +{ + return std::format( + "{} {}", z.zone_no(), + z.hemisphere() == zone::hemisphere::northern ? "northern" : "southern"); +} + } // namespace routemon::geo::utm diff --git a/server/src/log.cpp b/server/src/log.cpp index bb9fde2..5953c14 100644 --- a/server/src/log.cpp +++ b/server/src/log.cpp @@ -30,17 +30,7 @@ auto sink::level() const -> enum level { return lvl_; } auto sink::set_level(enum level lvl) -> void { lvl_ = lvl; } -auto sink::write(tmp_message msg) -> void -{ - auto sos = std::osyncstream{os_}; - sos << "[" << msg.lvl; - if (!msg.component.empty()) - sos << " " << msg.component; - sos << "] " << msg.txt; - for (auto const& [k, v] : msg.attrs) - sos << " " << k << "=" << std::quoted(v); - sos << std::endl; // we want the flush! -} +auto sink::write() -> std::osyncstream { return std::osyncstream{os_}; } auto make_sink(level lvl) -> std::shared_ptr { @@ -51,13 +41,17 @@ auto logger::log_at(log::level lvl, std::string_view fmt, std::format_args args) -> logger& { if (sink_->level() <= lvl) - sink_->write( - sink::tmp_message{ - .lvl = lvl, - .component = component_, - .txt = std::vformat(fmt, args), - .attrs = attrs_, - }); + { + auto sos = sink_->write(); + sos << "[" << lvl; + if (!component_.empty()) + sos << " " << component_; + sos << "] "; + std::vprint_unicode(sos, fmt, args); + for (auto const& [k, v] : attrs_) + sos << " " << k << "=" << std::quoted(v); + sos << std::endl; // we want the flush! + } return *this; } diff --git a/server/src/log.cppm b/server/src/log.cppm index dc8c2e1..87382f6 100644 --- a/server/src/log.cppm +++ b/server/src/log.cppm @@ -21,18 +21,10 @@ export class sink friend auto make_sink(level lvl) -> std::shared_ptr; public: - struct tmp_message - { - level lvl; - std::string_view component; - std::string_view txt; - std::map const& attrs; - }; - [[nodiscard]] auto level() const -> enum level; auto set_level(enum level lvl) -> void; - auto write(tmp_message msg) -> void; + auto write() -> std::osyncstream; }; export auto make_sink(level lvl) -> std::shared_ptr; diff --git a/server/src/srv.cpp b/server/src/srv.cpp index a901f8e..dc9c814 100644 --- a/server/src/srv.cpp +++ b/server/src/srv.cpp @@ -343,10 +343,10 @@ auto handler::handle_process_gpx(l0_ctx ctx, http::readable_request r) auto const before_read_gpx = chrono::steady_clock::now(); auto parse_res = r.p->get()[bhttp::field::content_encoding] == "x-deflate-raw" - ? std::move( - (co_await http::read_request>( - ctx, std::move(r))) - .body()) + ? std::move((co_await http:: + read_request>( + ctx, std::move(r))) + .body()) : std::move((co_await http::read_request( ctx, std::move(r))) .body()); diff --git a/server/src/trace.cpp b/server/src/trace.cpp index e7c00d0..f2935a9 100644 --- a/server/src/trace.cpp +++ b/server/src/trace.cpp @@ -10,6 +10,26 @@ import :trace; namespace routemon::trace { +class psrng +{ + mutable std::default_random_engine e_ = {}; + mutable std::uniform_int_distribution distr_ = {}; + mutable std::mutex mut_ = {}; + +public: + auto next() const -> std::uint64_t + { + auto lock = std::lock_guard{mut_}; + return distr_(e_); + } + + static auto instance() -> psrng const& + { + static auto const inst = psrng{}; + return inst; + } +}; + uuid7::uuid7() { namespace chrono = std::chrono; @@ -23,46 +43,51 @@ uuid7::uuid7() if (std::countl_zero(unix_time_ms) < 16) throw std::runtime_error{"system time too great"}; - auto rand = std::array{}; - int s = RAND_bytes(rand.data(), static_cast(rand.size())); - if (s != 1) - { - unsigned long e = ERR_get_error(); - throw std::runtime_error{std::format( - "failed to generate UUID(v7): {} ({}, code {})", - ERR_reason_error_string(e), ERR_lib_error_string(e), e)}; - } + auto const& rng = psrng::instance(); + auto const rand1 = rng.next(); + auto const rand2 = rng.next(); auto version = std::uint64_t{0b0111}; auto variant = std::uint64_t{0b10}; - hi_ |= unix_time_ms << 16; + hi_ = unix_time_ms << 16; hi_ |= version << 12; - hi_ |= std::uint64_t{rand[0]} << 4; - hi_ |= std::uint64_t{rand[1]}; - lo_ |= variant << 62; - lo_ |= std::uint64_t{rand[2]} << 54; - lo_ |= std::uint64_t{rand[3]} << 48; - lo_ |= std::uint64_t{rand[4]} << 40; - lo_ |= std::uint64_t{rand[5]} << 32; - lo_ |= std::uint64_t{rand[6]} << 24; - lo_ |= std::uint64_t{rand[7]} << 16; - lo_ |= std::uint64_t{rand[8]} << 8; - lo_ |= std::uint64_t{rand[9]}; + hi_ |= rand1 & 0x0000'0000'0000'0fff; + lo_ = variant << 62; + lo_ |= rand2 >> 2; } -auto uuid7::format(std::array& target) -> void +auto uuid7::format(std::span target) -> void { + auto hexnibs = + [](std::uint64_t v, std::span s) -> void + { + for (auto i = 0uz; i < n; i++) + { + static char const hextab[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', + }; + s[i] = hextab[(v >> 4 * (n - 1 - i)) & 0xf]; + } + }; + auto p____hi_hi = (hi_ & 0xffff'ffff'0000'0000) >> 32; auto p_hi_lo_hi = (hi_ & 0x0000'0000'ffff'0000) >> 16; auto p_lo_lo_hi = (hi_ & 0x0000'0000'0000'ffff) >> 0; auto p____hi_lo = (lo_ & 0xffff'0000'0000'0000) >> 48; auto p____lo_lo = (lo_ & 0x0000'ffff'ffff'ffff) >> 0; - std::format_to( - target.begin(), "{:0>8x}-{:0>4x}-{:0>4x}-{:0>4x}-{:0>12x}", p____hi_hi, - p_hi_lo_hi, p_lo_lo_hi, p____hi_lo, p____lo_lo); - target.back() = '\0'; + hexnibs(p____hi_hi, target.subspan<0, 8>()); + target[8] = '-'; + hexnibs(p_hi_lo_hi, target.subspan<9, 4>()); + target[13] = '-'; + hexnibs(p_lo_lo_hi, target.subspan<14, 4>()); + target[18] = '-'; + hexnibs(p____hi_lo, target.subspan<19, 4>()); + target[23] = '-'; + hexnibs(p____lo_lo, target.subspan<24, 12>()); + target[36] = '\0'; } id::id() { uuid7{}.format(chars_); } diff --git a/server/src/trace.cppm b/server/src/trace.cppm index deb84a0..fa743e1 100644 --- a/server/src/trace.cppm +++ b/server/src/trace.cppm @@ -7,13 +7,13 @@ namespace routemon::trace { class uuid7 { - std::uint64_t hi_ = 0; - std::uint64_t lo_ = 0; + std::uint64_t hi_; + std::uint64_t lo_; public: uuid7(); - auto format(std::array& target) -> void; + auto format(std::span target) -> void; }; export class id -- cgit v1.3