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");

Reply via email to