Prepare for try_lock optimization
So histogram observations never block
This commit is contained in:
@@ -342,13 +342,20 @@ struct Gauge::State {
|
||||
struct Histogram::State {
|
||||
std::span<const double> thresholds; // Bucket boundaries (sorted,
|
||||
// deduplicated, sizes never change)
|
||||
std::span<uint64_t> counts; // Count per bucket
|
||||
double sum; // Sum of observations
|
||||
uint64_t observations; // Total observation count
|
||||
|
||||
// Histogram counter data
|
||||
struct Counters {
|
||||
std::span<uint64_t> bucket_counts; // Count per bucket
|
||||
double sum = 0.0; // Sum of observations
|
||||
uint64_t observations = 0; // Total observation count
|
||||
};
|
||||
|
||||
Counters counters; // Main counter data
|
||||
|
||||
std::mutex
|
||||
mutex; // Per-thread, per-histogram mutex for consistent reads/writes
|
||||
|
||||
State() : sum(0.0), observations(0) {}
|
||||
State() {}
|
||||
friend struct Metric;
|
||||
};
|
||||
|
||||
@@ -499,13 +506,16 @@ struct Metric {
|
||||
assert(global_state);
|
||||
|
||||
// Accumulate bucket counts (mutex already held)
|
||||
for (size_t i = 0; i < instance->counts.size(); ++i) {
|
||||
global_state->counts[i] += instance->counts[i];
|
||||
for (size_t i = 0; i < instance->counters.bucket_counts.size();
|
||||
++i) {
|
||||
global_state->counters.bucket_counts[i] +=
|
||||
instance->counters.bucket_counts[i];
|
||||
}
|
||||
|
||||
// Accumulate sum and observations
|
||||
global_state->sum += instance->sum;
|
||||
global_state->observations += instance->observations;
|
||||
global_state->counters.sum += instance->counters.sum;
|
||||
global_state->counters.observations +=
|
||||
instance->counters.observations;
|
||||
}
|
||||
family->per_thread_state.erase(thread_it);
|
||||
}
|
||||
@@ -682,7 +692,8 @@ struct Metric {
|
||||
std::memset(counts_data, 0, bucket_count * sizeof(uint64_t));
|
||||
|
||||
ptr->thresholds = std::span<const double>(thresholds_data, bucket_count);
|
||||
ptr->counts = std::span<uint64_t>(counts_data, bucket_count);
|
||||
ptr->counters.bucket_counts =
|
||||
std::span<uint64_t>(counts_data, bucket_count);
|
||||
|
||||
// Ensure global accumulator exists for this label set
|
||||
auto &global_state = family->p->global_accumulated_values[key];
|
||||
@@ -701,7 +712,7 @@ struct Metric {
|
||||
|
||||
global_state->thresholds =
|
||||
std::span<const double>(global_thresholds_data, bucket_count);
|
||||
global_state->counts =
|
||||
global_state->counters.bucket_counts =
|
||||
std::span<uint64_t>(global_counts_data, bucket_count);
|
||||
}
|
||||
}
|
||||
@@ -1128,11 +1139,12 @@ struct Metric {
|
||||
|
||||
{
|
||||
std::lock_guard lock(instance->mutex);
|
||||
for (size_t i = 0; i < instance->counts.size(); ++i) {
|
||||
counts_snapshot[i] = instance->counts[i];
|
||||
for (size_t i = 0; i < instance->counters.bucket_counts.size();
|
||||
++i) {
|
||||
counts_snapshot[i] = instance->counters.bucket_counts[i];
|
||||
}
|
||||
sum_snapshot = instance->sum;
|
||||
observations_snapshot = instance->observations;
|
||||
sum_snapshot = instance->counters.sum;
|
||||
observations_snapshot = instance->counters.observations;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < bucket_count; ++i) {
|
||||
@@ -1145,11 +1157,12 @@ struct Metric {
|
||||
// Add global accumulated values
|
||||
if (instruction.aggregate_histogram.global_state) {
|
||||
auto *global_state = instruction.aggregate_histogram.global_state;
|
||||
for (size_t i = 0; i < global_state->counts.size(); ++i) {
|
||||
total_counts[i] += global_state->counts[i];
|
||||
for (size_t i = 0; i < global_state->counters.bucket_counts.size();
|
||||
++i) {
|
||||
total_counts[i] += global_state->counters.bucket_counts[i];
|
||||
}
|
||||
total_sum += global_state->sum;
|
||||
total_observations += global_state->observations;
|
||||
total_sum += global_state->counters.sum;
|
||||
total_observations += global_state->counters.observations;
|
||||
}
|
||||
|
||||
// Format explicit bucket counts
|
||||
@@ -1411,16 +1424,16 @@ update_histogram_buckets_simd(std::span<const double> thresholds,
|
||||
}
|
||||
|
||||
void Histogram::observe(double x) {
|
||||
assert(p->thresholds.size() == p->counts.size());
|
||||
assert(p->thresholds.size() == p->counters.bucket_counts.size());
|
||||
|
||||
std::lock_guard lock(p->mutex);
|
||||
|
||||
// Update bucket counts using SIMD
|
||||
update_histogram_buckets_simd(p->thresholds, p->counts, x, 0);
|
||||
update_histogram_buckets_simd(p->thresholds, p->counters.bucket_counts, x, 0);
|
||||
|
||||
// Update sum and observation count
|
||||
p->sum += x;
|
||||
p->observations++;
|
||||
p->counters.sum += x;
|
||||
p->counters.observations++;
|
||||
}
|
||||
|
||||
template <> Family<Counter>::Family() = default;
|
||||
|
||||
Reference in New Issue
Block a user