This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 94f4d27471 Allow to bulk allocate span's of Metrics (#10487)
94f4d27471 is described below
commit 94f4d27471f8cdd320d947252c898281b2fa67c9
Author: Leif Hedstrom <[email protected]>
AuthorDate: Mon Sep 25 15:38:57 2023 -0600
Allow to bulk allocate span's of Metrics (#10487)
---
include/api/Metrics.h | 10 ++++++++--
src/api/Metrics.cc | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
src/api/test_Metrics.cc | 23 +++++++++++++++++++++++
3 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/include/api/Metrics.h b/include/api/Metrics.h
index 1af20e42f9..89845c2b65 100644
--- a/include/api/Metrics.h
+++ b/include/api/Metrics.h
@@ -34,6 +34,8 @@
#include <string>
#include <string_view>
+#include "swoc/MemSpan.h"
+
#include "tscore/ink_assert.h"
namespace ts
@@ -44,8 +46,9 @@ private:
using self_type = Metrics;
public:
- using IntType = std::atomic<int64_t>;
- using IdType = int32_t; // Could be a tuple, but one way or another, they
have to be combined to an int32_t.
+ using IntType = std::atomic<int64_t>;
+ using IdType = int32_t; // Could be a tuple, but one way or another,
they have to be combined to an int32_t.
+ using SpanIntType = swoc::MemSpan<IntType>;
static constexpr uint16_t METRICS_MAX_BLOBS = 8192;
static constexpr uint16_t METRICS_MAX_SIZE = 2048;
// For a total of 16M metrics
@@ -86,6 +89,7 @@ public:
// Yes, we don't return objects here, but rather ID's and atomic's directly.
Treat
// the std::atomic<int64_t> as the underlying class for a single metric, and
be happy.
IdType newMetric(const std::string_view name);
+ SpanIntType newMetricSpan(size_t size, IdType *id = nullptr);
IdType lookup(const std::string_view name) const;
IntType *lookup(IdType id, std::string_view *name = nullptr) const;
@@ -106,6 +110,8 @@ public:
return lookup(newMetric(name));
}
+ bool rename(IdType id, const std::string_view name);
+
IntType &
operator[](IdType id)
{
diff --git a/src/api/Metrics.cc b/src/api/Metrics.cc
index c9e5c2eb55..8a67f9a8b5 100644
--- a/src/api/Metrics.cc
+++ b/src/api/Metrics.cc
@@ -122,6 +122,55 @@ Metrics::name(Metrics::IdType id) const
return result;
}
+Metrics::SpanIntType
+Metrics::newMetricSpan(size_t size, IdType *id)
+{
+ ink_release_assert(size <= Metrics::METRICS_MAX_SIZE);
+ std::lock_guard<std::mutex> lock(_mutex);
+
+ if (_cur_off + size > Metrics::METRICS_MAX_SIZE) {
+ _addBlob();
+ }
+
+ Metrics::IdType span_start = _makeId(_cur_blob, _cur_off);
+ Metrics::MetricStorage *blob = _blobs[_cur_blob];
+ Metrics::AtomicContainer &atomics = std::get<1>(*blob);
+ auto span = Metrics::SpanIntType(&atomics[_cur_off],
size);
+
+ std::fill(span.begin(), span.end(), 0);
+
+ if (id) {
+ *id = span_start;
+ }
+
+ _cur_off += size;
+
+ return span;
+}
+
+bool
+Metrics::rename(Metrics::IdType id, std::string_view name)
+{
+ auto [blob_ix, offset] = _splitID(id);
+ Metrics::MetricStorage *blob = _blobs[blob_ix];
+
+ // We can only rename metrics that are already allocated
+ if (!blob || (blob_ix == _cur_blob && offset > _cur_off)) {
+ return false;
+ }
+
+ std::string &cur = std::get<0>(std::get<0>(*blob)[offset]);
+
+ std::lock_guard<std::mutex> lock(_mutex);
+ if (cur.length() > 0) {
+ _lookups.erase(cur);
+ }
+ cur = name;
+ _lookups.emplace(cur, id);
+
+ return true;
+}
+
// Iterator implementation
void
Metrics::iterator::next()
diff --git a/src/api/test_Metrics.cc b/src/api/test_Metrics.cc
index 39f3794a9d..b08b5e046c 100644
--- a/src/api/test_Metrics.cc
+++ b/src/api/test_Metrics.cc
@@ -63,6 +63,29 @@ TEST_CASE("Metrics", "[libtsapi][Metrics]")
REQUIRE(m[0].load() == 42);
}
+ SECTION("Span allocation")
+ {
+ ts::Metrics::IdType span_id;
+ auto fooid = m.newMetric("foo"); // To see that span_id gets to 2
+ auto span = m.newMetricSpan(17, &span_id);
+
+ REQUIRE(span.size() == 17);
+ REQUIRE(fooid == 1);
+ REQUIRE(span_id == 2);
+
+ m.rename(span_id + 0, "span.0");
+ m.rename(span_id + 1, "span.1");
+ m.rename(span_id + 2, "span.2");
+ REQUIRE(m.name(fooid) == "foo");
+ REQUIRE(m.name(span_id + 0) == "span.0");
+ REQUIRE(m.name(span_id + 1) == "span.1");
+ REQUIRE(m.name(span_id + 2) == "span.2");
+ m.rename(fooid, "foo-new");
+ REQUIRE(m.name(fooid) == "foo-new");
+ REQUIRE(m.lookup("foo") == ts::Metrics::NOT_FOUND);
+ REQUIRE(m.lookup("foo-new") == fooid);
+ }
+
SECTION("lookup")
{
auto nm = m.lookupPtr("notametric");