diff --git a/pp/bare_bones/concepts.h b/pp/bare_bones/concepts.h index 605e0aac5..d211df04d 100644 --- a/pp/bare_bones/concepts.h +++ b/pp/bare_bones/concepts.h @@ -71,4 +71,7 @@ concept SteadyClockInterface = requires(Clock& clock) { { clock.now() }; }; +template +concept arithmetic = std::integral || std::floating_point; + } // namespace BareBones::concepts diff --git a/pp/bare_bones/snug_composite.h b/pp/bare_bones/snug_composite.h index e8526fe41..f16e16a87 100644 --- a/pp/bare_bones/snug_composite.h +++ b/pp/bare_bones/snug_composite.h @@ -79,8 +79,8 @@ class GenericDecodingTable { const GenericDecodingTable* decoding_table; PROMPP_ALWAYS_INLINE explicit Hasher(const GenericDecodingTable* _decoding_table = nullptr) noexcept : decoding_table(_decoding_table) {} - PROMPP_ALWAYS_INLINE size_t operator()(const std::string_view& str) const noexcept { return XXHash::hash(str); } - PROMPP_ALWAYS_INLINE size_t operator()(const std::string& str) const noexcept { return XXHash::hash(str); } + PROMPP_ALWAYS_INLINE size_t operator()(const std::string_view& str) const noexcept { return XXHash3::hash(str); } + PROMPP_ALWAYS_INLINE size_t operator()(const std::string& str) const noexcept { return XXHash3::hash(str); } template PROMPP_ALWAYS_INLINE size_t operator()(const Class& c) const noexcept { diff --git a/pp/bare_bones/tests/snug_composite_tests.cpp b/pp/bare_bones/tests/snug_composite_tests.cpp index 49f8b51ff..017cd7dec 100644 --- a/pp/bare_bones/tests/snug_composite_tests.cpp +++ b/pp/bare_bones/tests/snug_composite_tests.cpp @@ -141,7 +141,7 @@ TYPED_TEST(SnugComposite, should_return_same_id_for_same_data_with_hash) { this->fill_table_with_random_values(outcomes); std::string v = "12"; - auto hash_val = BareBones::XXHash::hash(v); + auto hash_val = BareBones::XXHash3::hash(v); auto id = outcomes.find_or_emplace(v, hash_val); EXPECT_EQ(id, outcomes.find_or_emplace(v, hash_val)); @@ -151,7 +151,7 @@ TYPED_TEST(SnugComposite, should_return_same_id_for_same_data_with_hash) { EXPECT_EQ(outcomes.find_or_emplace(v, hash_val), outcomes.find(v)); v = "21"; - hash_val = BareBones::XXHash::hash(v); + hash_val = BareBones::XXHash3::hash(v); id = outcomes.find_or_emplace(v); EXPECT_EQ(id, outcomes.find_or_emplace(v, hash_val)); diff --git a/pp/bare_bones/xxhash.h b/pp/bare_bones/xxhash.h index da670fe88..3d0c2968d 100644 --- a/pp/bare_bones/xxhash.h +++ b/pp/bare_bones/xxhash.h @@ -12,7 +12,7 @@ PRAGMA_DIAGNOSTIC(pop) namespace BareBones { -class XXHash { +class XXHash3 { public: template requires std::is_arithmetic_v @@ -30,15 +30,15 @@ class XXHash { [[nodiscard]] PROMPP_ALWAYS_INLINE uint64_t hash() const noexcept { return hash_; } [[nodiscard]] explicit PROMPP_ALWAYS_INLINE operator uint64_t() const noexcept { return hash_; } - auto operator<=>(const XXHash& other) const noexcept = default; + auto operator<=>(const XXHash3& other) const noexcept = default; - XXHash& operator=(uint64_t hash) noexcept { + XXHash3& operator=(uint64_t hash) noexcept { hash_ = hash; return *this; } PROMPP_ALWAYS_INLINE static uint64_t hash(const char* data, size_t size) noexcept { - XXHash hasher; + XXHash3 hasher; hasher.extend(data, size); return hasher.hash(); } @@ -50,4 +50,15 @@ class XXHash { uint64_t hash_{}; }; +class XXHash { + public: + PROMPP_ALWAYS_INLINE XXHash() { XXH64_reset(&state_, 0); } + + PROMPP_ALWAYS_INLINE void extend(std::string_view data) noexcept { XXH64_update(&state_, data.data(), data.length()); } + [[nodiscard]] PROMPP_ALWAYS_INLINE uint64_t digest() const noexcept { return XXH64_digest(&state_); } + + private: + XXH64_state_t state_; +}; + } // namespace BareBones diff --git a/pp/entrypoint/go_constants.cpp b/pp/entrypoint/go_constants.cpp index ed3a78f32..6befdd173 100644 --- a/pp/entrypoint/go_constants.cpp +++ b/pp/entrypoint/go_constants.cpp @@ -1,6 +1,7 @@ #include "go_constants.h" #include "head/serialization.h" +#include "metrics/storage.h" #include "prometheus/relabeler.h" namespace { @@ -13,4 +14,6 @@ static_assert(sizeof(PromPP::Prometheus::Relabel::InnerSeries) == Sizeof_InnerSe static_assert(sizeof(entrypoint::head::SerializedDataIterator) == Sizeof_SerializedDataIterator); +static_assert(sizeof(metrics::Storage::Iterator) == Sizeof_MetricsIterator); + } // namespace \ No newline at end of file diff --git a/pp/entrypoint/go_constants.h b/pp/entrypoint/go_constants.h index ec74157b1..82f538a5d 100644 --- a/pp/entrypoint/go_constants.h +++ b/pp/entrypoint/go_constants.h @@ -5,3 +5,5 @@ #define Sizeof_InnerSeries (Sizeof_SizeT + Sizeof_BareBonesVector + Sizeof_RoaringBitset) #define Sizeof_SerializedDataIterator 192 + +#define Sizeof_MetricsIterator 24 diff --git a/pp/entrypoint/metrics.cpp b/pp/entrypoint/metrics.cpp index 32e11daf0..f83820c0b 100644 --- a/pp/entrypoint/metrics.cpp +++ b/pp/entrypoint/metrics.cpp @@ -1,69 +1,47 @@ #include "metrics.h" -#include - -#include "metrics/counter.h" -#include "metrics/serializer.h" #include "metrics/storage.h" #include "primitives/go_model.h" #include "primitives/go_slice.h" -struct MetricsIterator { - metrics::Storage::Iterator iterator{metrics::storage().begin()}; - metrics::Serializer serializer; -}; - -using MetricsIteratorPtr = std::unique_ptr; - using PromPP::Primitives::Go::Label; using PromPP::Primitives::Go::SliceView; using PromPP::Primitives::Go::String; -extern "C" void prompp_metrics_iterator_ctor(void* res) { - struct Result { - MetricsIteratorPtr iterator; - }; - +extern "C" void prompp_metrics_iterator_ctor(void* args) { metrics::storage().remove_unused_pages(); - new (res) Result{.iterator = std::make_unique()}; + std::construct_at(static_cast(args), metrics::storage().begin()); } -extern "C" void prompp_metrics_iterator_dtor(void* args) { +extern "C" void prompp_metrics_iterator_next(void* args, void* res) { struct Arguments { - MetricsIteratorPtr iterator; - }; - - static_cast(args)->~Arguments(); -} - -extern "C" void prompp_metrics_iterator_serialize(void* args, void* res) { - struct Arguments { - MetricsIteratorPtr iterator; + metrics::Storage::Iterator* iterator; }; struct Result { - SliceView buffer; + const PromPP::Primitives::Go::Metric* metric; }; - const auto it = static_cast(args)->iterator.get(); + const auto in = static_cast(args); const auto out = static_cast(res); - if (it->iterator == metrics::Storage::end()) [[unlikely]] { - out->buffer.reset_to(nullptr, 0, 0); + if (*in->iterator == metrics::Storage::end()) [[unlikely]] { + out->metric = nullptr; } else { - const auto& buffer = it->serializer.serialize(it->iterator->page->labels(), it->iterator->metric); - out->buffer.reset_to(buffer.c_str(), buffer.size(), buffer.capacity()); - ++it->iterator; + out->metric = (*in->iterator)->go_metric(); + ++(*in->iterator); } } struct MetricsPageForTest final : metrics::MetricsPage { using MetricsPage::MetricsPage; - MetricsPageForTest(PromPP::Primitives::LabelViewSet&& label_set, const String& counter_name, uint64_t counter_value) - : MetricsPage(std::move(label_set)), emplace_count(static_cast(counter_name), counter_value) {} + MetricsPageForTest(const SliceView