From 7729398b197c56487241f68851cfcf81d559a43f Mon Sep 17 00:00:00 2001 From: Jorge Rocamora <33847633+aeroyorch@users.noreply.github.com> Date: Thu, 4 Jun 2026 21:53:12 +0200 Subject: [PATCH] Use std::less<> for Labels to enable heterogeneous lookup on C++14+ --- core/benchmarks/CMakeLists.txt | 1 + core/benchmarks/labels_bench.cc | 67 ++++++++++++++++++++++++++++++++ core/include/prometheus/labels.h | 10 +++++ 3 files changed, 78 insertions(+) create mode 100644 core/benchmarks/labels_bench.cc diff --git a/core/benchmarks/CMakeLists.txt b/core/benchmarks/CMakeLists.txt index c1294d5ad..74120e17c 100644 --- a/core/benchmarks/CMakeLists.txt +++ b/core/benchmarks/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable(benchmarks gauge_bench.cc histogram_bench.cc info_bench.cc + labels_bench.cc registry_bench.cc summary_bench.cc ) diff --git a/core/benchmarks/labels_bench.cc b/core/benchmarks/labels_bench.cc new file mode 100644 index 000000000..a9c8d4612 --- /dev/null +++ b/core/benchmarks/labels_bench.cc @@ -0,0 +1,67 @@ +#include + +#include +#include +#include +#include +#include + +#include "benchmark_helpers.h" + +#if defined(__cpp_lib_string_view) && defined(__cpp_lib_generic_associative_lookup) +#include + +using Plain = std::map; +using Transparent = std::map>; + +template +static Map MakeMap(std::size_t size, std::size_t key_length, + std::vector& keys) { + Map map; + keys.reserve(size); + for (std::size_t i = 0; i < size; ++i) { + auto key = GenerateRandomString(key_length); + map.emplace(key, "value"); + keys.push_back(std::move(key)); + } + return map; +} + +template +static void BM_Labels_LookupView(benchmark::State& state) { + std::vector keys; + const auto map = MakeMap(state.range(0), state.range(1), keys); + std::size_t i = 0; + while (state.KeepRunning()) { + const std::string_view key = keys[i]; + if (++i == keys.size()) i = 0; + if constexpr (Heterogeneous) { + benchmark::DoNotOptimize(map.find(key)); + } else { + benchmark::DoNotOptimize(map.find(std::string(key))); + } + } +} + +template +static void BM_Labels_LookupString(benchmark::State& state) { + std::vector keys; + const auto map = MakeMap(state.range(0), state.range(1), keys); + std::size_t i = 0; + while (state.KeepRunning()) { + const std::string& key = keys[i]; + if (++i == keys.size()) i = 0; + benchmark::DoNotOptimize(map.find(key)); + } +} + +BENCHMARK_TEMPLATE(BM_Labels_LookupView, Plain, false) + ->ArgsProduct({{4, 16}, {8, 32}}); +BENCHMARK_TEMPLATE(BM_Labels_LookupView, Transparent, true) + ->ArgsProduct({{4, 16}, {8, 32}}); +BENCHMARK_TEMPLATE(BM_Labels_LookupString, Plain) + ->ArgsProduct({{4, 16}, {8, 32}}); +BENCHMARK_TEMPLATE(BM_Labels_LookupString, Transparent) + ->ArgsProduct({{4, 16}, {8, 32}}); + +#endif diff --git a/core/include/prometheus/labels.h b/core/include/prometheus/labels.h index d6fce0ff4..9790c0121 100644 --- a/core/include/prometheus/labels.h +++ b/core/include/prometheus/labels.h @@ -1,12 +1,22 @@ #pragma once +#if defined(__cpp_lib_generic_associative_lookup) +#include +#endif #include #include namespace prometheus { /// \brief Multiple labels and their value. +/// +/// Uses the transparent comparator std::less<> on C++14 and newer to allow +/// heterogeneous lookup, falling back to the default comparator on C++11. +#if defined(__cpp_lib_generic_associative_lookup) +using Labels = std::map>; +#else using Labels = std::map; +#endif /// \brief Single label and its value. using Label = Labels::value_type;