From 81cd7fe2fbe2fbd5e363f2f4edc4fac388cb06ca Mon Sep 17 00:00:00 2001 From: cong1920 Date: Thu, 26 Mar 2026 01:31:59 -0700 Subject: [PATCH] [http_server] Cache parameter child pointer for O(1) lookup fallback In find(), when a static child lookup misses, the code previously did a linear scan of ALL children to find a {{param}} child. This is O(n) per tree level for every parameterized route lookup. Fix: Cache param_child_ pointer during find_or_create(), so find() can fall back to it in O(1) instead of scanning. Benchmark results (median, 25 iterations, WSL2 g++ -O2): Before After Change insert: 313.3 ns/op 299.2 ns/op -4.5% lookup hit: 80.7 ns/op 72.7 ns/op -9.9% lookup miss: 45.0 ns/op 36.6 ns/op -18.7% --- .../http_server/dynamic_routing_table.hh | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/http_server/http_server/dynamic_routing_table.hh b/libraries/http_server/http_server/dynamic_routing_table.hh index 7448371..579d310 100644 --- a/libraries/http_server/http_server/dynamic_routing_table.hh +++ b/libraries/http_server/http_server/dynamic_routing_table.hh @@ -53,7 +53,12 @@ template struct drt_node { std::string_view k = r.substr(s, c - s); if (children_.find(k) == children_.end()) { - children_[k] = pool_.allocate(pool_); + auto* child = pool_.allocate(pool_); + children_[k] = child; + // Cache the parameter child pointer for O(1) lookup in find() + if (k.size() > 4 and k[0] == '{' and k[1] == '{' and + k[k.size() - 2] == '}' and k[k.size() - 1] == '}') + param_child_ = child; } return children_[k]->find_or_create(r, c); } @@ -100,20 +105,15 @@ template struct drt_node { return it2; } - { - // if one child is a url param {{param_name}}, choose it - for (const auto& kv : children_) { - auto name = kv.first; - if (name.size() > 4 and name[0] == '{' and name[1] == '{' and - name[name.size() - 2] == '}' and name[name.size() - 1] == '}') - return kv.second->find(r, c); - } - return end(); - } + // O(1) fallback to cached parameter child instead of O(n) linear scan + if (param_child_) + return param_child_->find(r, c); + return end(); } V v_; std::unordered_map children_; + drt_node* param_child_ = nullptr; // cached {{param}} child for O(1) lookup drt_node_pool& pool_; };