Intern label sets
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <immintrin.h>
|
||||
@@ -81,6 +82,7 @@ static std::string_view arena_copy_string(std::string_view str,
|
||||
struct LabelsKey {
|
||||
ArenaVector<std::pair<std::string_view, std::string_view>> labels;
|
||||
|
||||
// Arena-owning constructor (copies strings into arena)
|
||||
LabelsKey(std::span<const std::pair<std::string_view, std::string_view>> l,
|
||||
ArenaAllocator &arena)
|
||||
: labels(&arena) {
|
||||
@@ -302,6 +304,16 @@ struct Metric {
|
||||
return *histogramFamilies;
|
||||
}
|
||||
|
||||
// Global label interning set to avoid duplicate LabelsKey allocations
|
||||
static auto &get_interned_labels() {
|
||||
using InternSet = std::unordered_set<LabelsKey, std::hash<LabelsKey>,
|
||||
std::equal_to<LabelsKey>,
|
||||
ArenaStlAllocator<LabelsKey>>;
|
||||
static InternSet *internedLabels =
|
||||
new InternSet(ArenaStlAllocator<LabelsKey>(&get_global_arena()));
|
||||
return *internedLabels;
|
||||
}
|
||||
|
||||
// Thread cleanup for per-family thread-local storage
|
||||
struct ThreadInit {
|
||||
ArenaAllocator arena;
|
||||
@@ -379,6 +391,27 @@ struct Metric {
|
||||
|
||||
// Thread cleanup now handled by ThreadInit RAII
|
||||
|
||||
// Intern labels to avoid duplicate arena allocations
|
||||
static const LabelsKey &intern_labels(
|
||||
std::span<const std::pair<std::string_view, std::string_view>> labels) {
|
||||
auto &interned_set = get_interned_labels();
|
||||
|
||||
// Create temporary lookup key using stack-allocated arena
|
||||
ArenaAllocator lookup_arena(1024); // Small arena for lookups
|
||||
LabelsKey lookup_key{labels, lookup_arena};
|
||||
|
||||
// Use standard hash set lookup
|
||||
auto it = interned_set.find(lookup_key);
|
||||
if (it != interned_set.end()) {
|
||||
return *it;
|
||||
}
|
||||
|
||||
// Not found - create and intern new key
|
||||
LabelsKey new_key{labels, get_global_arena()};
|
||||
auto result = interned_set.emplace(std::move(new_key));
|
||||
return *result.first;
|
||||
}
|
||||
|
||||
static Counter create_counter_instance(
|
||||
Family<Counter> *family,
|
||||
std::span<const std::pair<std::string_view, std::string_view>> labels) {
|
||||
@@ -386,7 +419,7 @@ struct Metric {
|
||||
(void)thread_init;
|
||||
|
||||
std::unique_lock<std::mutex> _{mutex};
|
||||
LabelsKey key{labels, get_global_arena()};
|
||||
const LabelsKey &key = intern_labels(labels);
|
||||
|
||||
// Validate that labels aren't already registered as callback
|
||||
validate_or_abort(family->p->callbacks.find(key) ==
|
||||
@@ -419,7 +452,7 @@ struct Metric {
|
||||
Family<Gauge> *family,
|
||||
std::span<const std::pair<std::string_view, std::string_view>> labels) {
|
||||
std::unique_lock<std::mutex> _{mutex};
|
||||
LabelsKey key{labels, get_global_arena()};
|
||||
const LabelsKey &key = intern_labels(labels);
|
||||
|
||||
// Validate that labels aren't already registered as callback
|
||||
validate_or_abort(family->p->callbacks.find(key) ==
|
||||
@@ -444,7 +477,7 @@ struct Metric {
|
||||
(void)thread_init;
|
||||
|
||||
std::unique_lock<std::mutex> _{mutex};
|
||||
LabelsKey key{labels, get_global_arena()};
|
||||
const LabelsKey &key = intern_labels(labels);
|
||||
|
||||
// Ensure thread state exists
|
||||
auto thread_id = std::this_thread::get_id();
|
||||
@@ -1163,7 +1196,7 @@ void Family<Counter>::register_callback(
|
||||
std::span<const std::pair<std::string_view, std::string_view>> labels,
|
||||
MetricCallback<Counter> callback) {
|
||||
std::unique_lock<std::mutex> _{Metric::mutex};
|
||||
LabelsKey key{labels, Metric::get_global_arena()};
|
||||
const LabelsKey &key = Metric::intern_labels(labels);
|
||||
|
||||
// Validate that labels aren't already in use by create() calls
|
||||
for (const auto &[thread_id, per_thread] : p->per_thread_state) {
|
||||
@@ -1186,7 +1219,7 @@ void Family<Gauge>::register_callback(
|
||||
std::span<const std::pair<std::string_view, std::string_view>> labels,
|
||||
MetricCallback<Gauge> callback) {
|
||||
std::unique_lock<std::mutex> _{Metric::mutex};
|
||||
LabelsKey key{labels, Metric::get_global_arena()};
|
||||
const LabelsKey &key = Metric::intern_labels(labels);
|
||||
|
||||
// Validate that labels aren't already in use by create() calls
|
||||
validate_or_abort(p->instances.find(key) == p->instances.end(),
|
||||
|
||||
Reference in New Issue
Block a user