diff --git a/src/metric.cpp b/src/metric.cpp index 0c1efae..cf1b5bd 100644 --- a/src/metric.cpp +++ b/src/metric.cpp @@ -22,7 +22,9 @@ #include #include +#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) #include +#endif #include #include "arena.hpp" @@ -1398,8 +1400,10 @@ void Gauge::set(double x) { Histogram::Histogram() = default; // Vectorized histogram bucket updates with mutex protection for consistency -// AVX-optimized implementation for high performance +// AVX-optimized implementation for high performance on x86-64, scalar fallback +// on other architectures (e.g., ARM64). +#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) __attribute__((target("avx"))) static void update_histogram_buckets_simd(std::span thresholds, std::span counts, double x, @@ -1439,6 +1443,22 @@ update_histogram_buckets_simd(std::span thresholds, } } } +#endif + +static void update_histogram_buckets(std::span thresholds, + std::span counts, double x, + size_t start_idx) { +#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) + update_histogram_buckets_simd(thresholds, counts, x, start_idx); +#else + const size_t size = thresholds.size(); + for (size_t i = start_idx; i < size; ++i) { + if (x <= thresholds[i]) { + counts[i]++; + } + } +#endif +} void Histogram::observe(double x) { assert(p->thresholds.size() == p->shared.bucket_counts.size()); @@ -1459,15 +1479,15 @@ void Histogram::observe(double x) { } // Update shared directly - update_histogram_buckets_simd(p->thresholds, p->shared.bucket_counts, x, 0); + update_histogram_buckets(p->thresholds, p->shared.bucket_counts, x, 0); p->shared.sum += x; p->shared.observations++; p->mutex.unlock(); } else { // Slow path: accumulate in pending (lock-free) - update_histogram_buckets_simd(p->thresholds, p->pending.bucket_counts, x, - 0); + update_histogram_buckets(p->thresholds, p->pending.bucket_counts, x, + 0); p->pending.sum += x; p->pending.observations++; }