From d7de96ef9451b33e9171ef2062efb2550057c2fb Mon Sep 17 00:00:00 2001 From: Weaselbot Date: Fri, 26 Jun 2026 10:49:53 -0400 Subject: [PATCH] Support building on ARM by providing scalar histogram fallback The metrics histogram update code unconditionally included and used __attribute__((target("avx"))) SSE/AVX intrinsics, which only exist on x86-64. This prevented the project from compiling on ARM64. Guard the x86-64 SIMD implementation and the include with an architecture check, and add a portable scalar fallback for non-x86-64 platforms (e.g., ARM64). A thin wrapper function keeps the call sites unchanged and preserves the AVX fast path on x86-64. Closes #3 --- src/metric.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) 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++; }