Skip to content

Commit

Permalink
feat: don't create temporary objects for serialization
Browse files Browse the repository at this point in the history
Fix: #646
  • Loading branch information
gjasny committed Dec 28, 2023
1 parent 2a39067 commit 5675de5
Show file tree
Hide file tree
Showing 27 changed files with 551 additions and 255 deletions.
2 changes: 1 addition & 1 deletion core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ add_library(core
src/gauge.cc
src/histogram.cc
src/info.cc
src/iovector.cc
src/registry.cc
src/serializer.cc
src/summary.cc
src/text_serializer.cc
)
Expand Down
9 changes: 2 additions & 7 deletions core/include/prometheus/collectable.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
#pragma once

#include <vector>

#include "prometheus/detail/core_export.h"

namespace prometheus {
struct MetricFamily;
}
#include "prometheus/serializer.h"

namespace prometheus {

Expand All @@ -19,7 +14,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Collectable {
virtual ~Collectable() = default;

/// \brief Returns a list of metrics and their samples.
virtual std::vector<MetricFamily> Collect() const = 0;
virtual void Collect(const Serializer& out) const = 0;
};

} // namespace prometheus
5 changes: 2 additions & 3 deletions core/include/prometheus/family.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>

#include "prometheus/client_metric.h"
#include "prometheus/collectable.h"
#include "prometheus/detail/core_export.h"
#include "prometheus/detail/future_std.h"
#include "prometheus/detail/utils.h"
#include "prometheus/labels.h"
#include "prometheus/metric_family.h"
#include "prometheus/serializer.h"

// IWYU pragma: no_include "prometheus/counter.h"
// IWYU pragma: no_include "prometheus/gauge.h"
Expand Down Expand Up @@ -140,7 +139,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable {
/// Collect is called by the Registry when collecting metrics.
///
/// \return Zero or more samples for each dimensional data.
std::vector<MetricFamily> Collect() const override;
void Collect(const Serializer& out) const override;

private:
std::unordered_map<Labels, std::unique_ptr<T>, detail::LabelHasher> metrics_;
Expand Down
27 changes: 27 additions & 0 deletions core/include/prometheus/iovector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

#include "prometheus/detail/core_export.h"

namespace prometheus {

struct PROMETHEUS_CPP_CORE_EXPORT IOVector {
using ByteVector = std::vector<std::uint8_t>;

bool empty() const;

std::size_t size() const;

std::size_t copy(std::size_t offset, void* buffer,
std::size_t bufferSize) const;

void add(const std::string& str, std::size_t chunkSize);

std::vector<ByteVector> data;
};

} // namespace prometheus
1 change: 0 additions & 1 deletion core/include/prometheus/metric_family.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ struct PROMETHEUS_CPP_CORE_EXPORT MetricFamily {
std::string name;
std::string help;
MetricType type = MetricType::Untyped;
std::vector<ClientMetric> metric;
};
} // namespace prometheus
4 changes: 2 additions & 2 deletions core/include/prometheus/registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "prometheus/detail/core_export.h"
#include "prometheus/family.h"
#include "prometheus/labels.h"
#include "prometheus/metric_family.h"
#include "prometheus/serializer.h"

namespace prometheus {

Expand Down Expand Up @@ -79,7 +79,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable {
/// function.
///
/// \return Zero or more metrics and their samples.
std::vector<MetricFamily> Collect() const override;
void Collect(const Serializer& out) const override;

/// \brief Removes a metrics family from the registry.
///
Expand Down
12 changes: 5 additions & 7 deletions core/include/prometheus/serializer.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#pragma once

#include <iosfwd>
#include <string>
#include <vector>

#include "prometheus/client_metric.h"
#include "prometheus/detail/core_export.h"
#include "prometheus/metric_family.h"

Expand All @@ -12,9 +9,10 @@ namespace prometheus {
class PROMETHEUS_CPP_CORE_EXPORT Serializer {
public:
virtual ~Serializer() = default;
virtual std::string Serialize(const std::vector<MetricFamily>&) const;
virtual void Serialize(std::ostream& out,
const std::vector<MetricFamily>& metrics) const = 0;

virtual void SerializeHelp(const MetricFamily& family) const = 0;
virtual void SerializeMetrics(const MetricFamily& family,
const ClientMetric& metric) const = 0;
};

} // namespace prometheus
18 changes: 14 additions & 4 deletions core/include/prometheus/text_serializer.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
#pragma once

#include <cstddef>
#include <iosfwd>
#include <vector>

#include "prometheus/client_metric.h"
#include "prometheus/detail/core_export.h"
#include "prometheus/iovector.h"
#include "prometheus/metric_family.h"
#include "prometheus/serializer.h"

namespace prometheus {

class PROMETHEUS_CPP_CORE_EXPORT TextSerializer : public Serializer {
public:
using Serializer::Serialize;
void Serialize(std::ostream& out,
const std::vector<MetricFamily>& metrics) const override;
TextSerializer(IOVector& ioVector);

void SerializeHelp(const MetricFamily& family) const override;
void SerializeMetrics(const MetricFamily& family,
const ClientMetric& metric) const override;

private:
void Add(const std::ostringstream& stream) const;

IOVector& ioVector_;
static constexpr std::size_t chunkSize_ = 1 * 1024 * 1024;
};

} // namespace prometheus
13 changes: 8 additions & 5 deletions core/src/family.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "prometheus/gauge.h"
#include "prometheus/histogram.h"
#include "prometheus/info.h"
#include "prometheus/metric_family.h"
#include "prometheus/summary.h"

namespace prometheus {
Expand Down Expand Up @@ -86,22 +87,24 @@ const Labels& Family<T>::GetConstantLabels() const {
}

template <typename T>
std::vector<MetricFamily> Family<T>::Collect() const {
void Family<T>::Collect(const Serializer& out) const {
std::lock_guard<std::mutex> lock{mutex_};

if (metrics_.empty()) {
return {};
return;
}

auto family = MetricFamily{};
family.name = name_;
family.help = help_;
family.type = T::metric_type;
family.metric.reserve(metrics_.size());

out.SerializeHelp(family);

for (const auto& m : metrics_) {
family.metric.push_back(std::move(CollectMetric(m.first, m.second.get())));
auto&& metric = CollectMetric(m.first, m.second.get());
out.SerializeMetrics(family, metric);
}
return {family};
}

template <typename T>
Expand Down
58 changes: 58 additions & 0 deletions core/src/iovector.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "prometheus/iovector.h"

#include <algorithm>
#include <iterator>
#include <memory>
#include <numeric>

namespace prometheus {

bool IOVector::empty() const { return data.empty() || !size(); }

std::size_t IOVector::size() const {
return std::accumulate(begin(data), end(data), std::size_t{0},
[](std::size_t size, const ByteVector& chunk) {
return size + chunk.size();
});
}

std::size_t IOVector::copy(std::size_t offset, void* buffer,
std::size_t bufferSize) const {
std::size_t copied = 0;
for (const auto& chunk : data) {
if (offset >= chunk.size()) {
offset -= chunk.size();
continue;
}

auto chunkSize = std::min(chunk.size() - offset, bufferSize - copied);
std::copy_n(chunk.data() + offset, chunkSize,
reinterpret_cast<std::uint8_t*>(buffer) + copied);
copied += chunkSize;
offset = 0;

if (copied == bufferSize) {
break;
}
}
return copied;
}

void IOVector::add(const std::string& str, std::size_t chunkSize) {
std::size_t size = str.size();
std::size_t offset = 0;

while (size > 0U) {
if (data.empty() || data.back().size() >= chunkSize) {
data.emplace_back();
data.back().reserve(chunkSize);
}
auto&& chunk = data.back();
const auto toAdd = std::min(size, chunkSize - chunk.size());
chunk.insert(chunk.end(), str.data() + offset, str.data() + offset + toAdd);

size -= toAdd;
offset += toAdd;
}
}
} // namespace prometheus
22 changes: 8 additions & 14 deletions core/src/registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <algorithm>
#include <iterator>
#include <stdexcept>
#include <tuple>

#include "prometheus/counter.h"
#include "prometheus/detail/future_std.h"
Expand All @@ -16,11 +15,9 @@ namespace prometheus {

namespace {
template <typename T>
void CollectAll(std::vector<MetricFamily>& results, const T& families) {
void CollectAll(const Serializer& out, const T& families) {
for (auto&& collectable : families) {
auto metrics = collectable->Collect();
results.insert(results.end(), std::make_move_iterator(metrics.begin()),
std::make_move_iterator(metrics.end()));
collectable->Collect(out);
}
}

Expand All @@ -43,17 +40,14 @@ Registry::Registry(InsertBehavior insert_behavior)

Registry::~Registry() = default;

std::vector<MetricFamily> Registry::Collect() const {
void Registry::Collect(const Serializer& out) const {
std::lock_guard<std::mutex> lock{mutex_};
auto results = std::vector<MetricFamily>{};

CollectAll(results, counters_);
CollectAll(results, gauges_);
CollectAll(results, histograms_);
CollectAll(results, infos_);
CollectAll(results, summaries_);

return results;
CollectAll(out, counters_);
CollectAll(out, gauges_);
CollectAll(out, histograms_);
CollectAll(out, infos_);
CollectAll(out, summaries_);
}

template <>
Expand Down
13 changes: 0 additions & 13 deletions core/src/serializer.cc

This file was deleted.

Loading

0 comments on commit 5675de5

Please sign in to comment.