[libcxx-commits] [libcxx] [libc++] Optimize {std, ranges}::for_each for iterating over __trees (PR #164405)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 2 08:10:26 PST 2025


================
@@ -44,12 +46,98 @@ int main(int argc, char** argv) {
           ->Arg(50) // non power-of-two
           ->Arg(8192);
     };
-    bm.operator()<std::vector<int>>("std::for_each(vector<int>)", std_for_each);
-    bm.operator()<std::deque<int>>("std::for_each(deque<int>)", std_for_each);
-    bm.operator()<std::list<int>>("std::for_each(list<int>)", std_for_each);
-    bm.operator()<std::vector<int>>("rng::for_each(vector<int>)", std::ranges::for_each);
-    bm.operator()<std::deque<int>>("rng::for_each(deque<int>)", std::ranges::for_each);
-    bm.operator()<std::list<int>>("rng::for_each(list<int>)", std::ranges::for_each);
+    sequence_bm.operator()<std::vector<int>>("std::for_each(vector<int>)", std_for_each);
+    sequence_bm.operator()<std::deque<int>>("std::for_each(deque<int>)", std_for_each);
+    sequence_bm.operator()<std::list<int>>("std::for_each(list<int>)", std_for_each);
+    sequence_bm.operator()<std::vector<int>>("rng::for_each(vector<int>)", std::ranges::for_each);
+    sequence_bm.operator()<std::deque<int>>("rng::for_each(deque<int>)", std::ranges::for_each);
+    sequence_bm.operator()<std::list<int>>("rng::for_each(list<int>)", std::ranges::for_each);
+
+    auto associative_bm =
+        []<class Container, bool IsMapLike>(
+            std::type_identity<Container>, std::bool_constant<IsMapLike>, std::string name, auto for_each) {
+          benchmark::RegisterBenchmark(
+              name,
+              [for_each](auto& st) {
+                Container c;
+                for (size_t i = 0; i != st.range(0); ++i) {
+                  if constexpr (IsMapLike)
+                    c.emplace(i);
+                  else
+                    c.emplace(i, i);
+                }
+
+                for (auto _ : st) {
+                  benchmark::DoNotOptimize(c);
+                  for_each(c.begin(), c.end(), [](auto v) { benchmark::DoNotOptimize(&v); });
+                }
+              })
+              ->Arg(8)
+              ->Arg(32)
+              ->Arg(50) // non power-of-two
+              ->Arg(8192);
+        };
+    associative_bm(std::type_identity<std::set<int>>{},
+                   std::false_type{},
+                   "rng::for_each(set<int>::iterator)",
+                   std::ranges::for_each);
+    associative_bm(std::type_identity<std::multiset<int>>{},
+                   std::false_type{},
+                   "rng::for_each(multiset<int>::iterator)",
+                   std::ranges::for_each);
+    associative_bm(std::type_identity<std::map<int, int>>{},
+                   std::true_type{},
+                   "rng::for_each(map<int>::iterator)",
+                   std::ranges::for_each);
+    associative_bm(std::type_identity<std::multimap<int, int>>{},
+                   std::true_type{},
+                   "rng::for_each(multimap<int>::iterator)",
+                   std::ranges::for_each);
+
+    auto associative_ranges_bm =
+        []<class Container, bool IsMapLike>(
+            std::type_identity<Container>, std::bool_constant<IsMapLike>, std::string name, auto for_each) {
+          benchmark::RegisterBenchmark(
+              name,
+              [for_each](auto& st) {
+                Container c;
+                for (size_t i = 0; i != st.range(0); ++i) {
+                  if constexpr (IsMapLike)
+                    c.emplace(i);
+                  else
+                    c.emplace(i, i);
+                }
+
+                for (auto _ : st) {
+                  benchmark::DoNotOptimize(c);
+                  for_each(c, [](auto v) { benchmark::DoNotOptimize(v); });
+                }
+              })
+              ->Arg(8)
+              ->Arg(32)
+              ->Arg(50) // non power-of-two
+              ->Arg(8192);
+        };
+    associative_ranges_bm(
+        std::type_identity<std::set<int>>{},
+        std::false_type{},
+        "rng::for_each(set<int>::iterator)",
----------------
ldionne wrote:

These benchmark names are wrong, they should be `rng::for_each(set<int>)`.

https://github.com/llvm/llvm-project/pull/164405


More information about the libcxx-commits mailing list