[libcxx-commits] [libcxx] [libc++][WIP] use linear search instead of binary search for small flat_map (PR #211794)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 24 06:46:55 PDT 2026


https://github.com/huixie90 created https://github.com/llvm/llvm-project/pull/211794

None

>From c0af2a86aaf5a970f1fb1f3911f500d67125244f Mon Sep 17 00:00:00 2001
From: Hui Xie <hui.xie1990 at gmail.com>
Date: Fri, 24 Jul 2026 14:46:31 +0100
Subject: [PATCH] [libc++][WIP] use linear search instead of binary search for
 small flat_map

---
 libcxx/include/__flat_map/flat_map.h                 |  8 ++++++++
 .../associative/associative_container_benchmarks.h   | 12 ++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h
index 50487cada24c0..8b15491a60dfc 100644
--- a/libcxx/include/__flat_map/flat_map.h
+++ b/libcxx/include/__flat_map/flat_map.h
@@ -15,6 +15,7 @@
 #include <__algorithm/min.h>
 #include <__algorithm/ranges_adjacent_find.h>
 #include <__algorithm/ranges_equal.h>
+#include <__algorithm/ranges_find.h>
 #include <__algorithm/ranges_inplace_merge.h>
 #include <__algorithm/ranges_sort.h>
 #include <__algorithm/ranges_unique.h>
@@ -64,6 +65,7 @@
 #include <__vector/vector.h>
 #include <initializer_list>
 #include <stdexcept>
+#include <type_traits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -989,6 +991,12 @@ class flat_map {
 
   template <class _Self, class _Kp>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) {
+    auto __key_iter = std::ranges::find(__self.__containers_.keys, __key);
+    auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter);
+
+    using Res = std::conditional_t<std::is_const_v<std::remove_reference_t<_Self>>, const_iterator, iterator>;
+    return Res(__key_iter, __mapped_iter);
+
     auto __it   = __self.lower_bound(__key);
     auto __last = __self.end();
     if (__it == __last || __self.__compare_(__key, __it->first)) {
diff --git a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
index a55f187d2ac80..93d06a020f759 100644
--- a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
+++ b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
@@ -66,7 +66,7 @@ void associative_container_benchmarks(std::string container) {
     benchmark::RegisterBenchmark(container + "::" + operation, f)->Arg(0)->Arg(32)->Arg(1024)->Arg(8192);
   };
   auto bench_non_empty = [&](std::string operation, auto f) {
-    benchmark::RegisterBenchmark(container + "::" + operation, f)->Arg(32)->Arg(1024)->Arg(8192);
+    benchmark::RegisterBenchmark(container + "::" + operation, f)->Arg(1)->Arg(4)->Arg(8)->Arg(16)->Arg(32)->Arg(1024)->Arg(8192);
   };
 
   static constexpr bool is_multi_key_container =
@@ -692,9 +692,17 @@ void associative_container_benchmarks(std::string container) {
       const std::size_t size = st.range(0);
       std::vector<Value> in  = make_value_types(generate_unique_keys(size));
       Container c(in.begin(), in.end());
+      std::vector<Key> keys;
+      for(size_t i = 0; i <in.size(); ++i) {
+        keys.push_back(get_key(in[getRandomEngine()() % in.size()]));
+      }
+      size_t i = 0;
 
       for (auto _ : st) {
-        auto result = func(c, get_key(in[getRandomEngine()() % in.size()]));
+      //st.PauseTiming();
+      const auto& key =  keys[++i%keys.size()];
+      //st.ResumeTiming();
+        auto result = func(c, key);
         benchmark::DoNotOptimize(c);
         benchmark::DoNotOptimize(result);
         benchmark::ClobberMemory();



More information about the libcxx-commits mailing list