Skip to content

Commit

Permalink
[metric]Optimize summary (#761)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos committed Aug 19, 2024
1 parent 1d73d24 commit e21db0c
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 54 deletions.
25 changes: 15 additions & 10 deletions include/ylt/metric/counter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ class basic_static_counter : public static_metric {
uint32_t dupli_count_ = 2;
};

template <size_t N>
template <typename Key>
struct array_hash {
size_t operator()(const std::array<std::string, N> &arr) const {
size_t operator()(const Key &arr) const {
unsigned int seed = 131;
unsigned int hash = 0;

Expand All @@ -185,11 +185,10 @@ struct array_hash {
using counter_t = basic_static_counter<int64_t>;
using counter_d = basic_static_counter<double>;

template <typename T, size_t N>
using dynamic_metric_hash_map =
std::unordered_map<std::array<std::string, N>, T, array_hash<N>>;
template <typename Key, typename T>
using dynamic_metric_hash_map = std::unordered_map<Key, T, array_hash<Key>>;

template <typename value_type, size_t N>
template <typename value_type, uint8_t N>
class basic_dynamic_counter : public dynamic_metric {
public:
// dynamic labels value
Expand Down Expand Up @@ -264,8 +263,12 @@ class basic_dynamic_counter : public dynamic_metric {
return val;
}

dynamic_metric_hash_map<thread_local_value<value_type>, N> value_map() {
dynamic_metric_hash_map<thread_local_value<value_type>, N> map;
dynamic_metric_hash_map<std::array<std::string, N>,
thread_local_value<value_type>>
value_map() {
dynamic_metric_hash_map<std::array<std::string, N>,
thread_local_value<value_type>>
map;
{
std::lock_guard lock(mtx_);
map = value_map_;
Expand Down Expand Up @@ -378,7 +381,7 @@ class basic_dynamic_counter : public dynamic_metric {

bool has_label_value(const std::vector<std::string> &label_value) override {
std::array<std::string, N> arr{};
size_t size = (std::min)(N, label_value.size());
size_t size = (std::min)((size_t)N, label_value.size());
for (size_t i = 0; i < size; i++) {
arr[i] = label_value[i];
}
Expand Down Expand Up @@ -470,7 +473,9 @@ class basic_dynamic_counter : public dynamic_metric {
}

std::mutex mtx_;
dynamic_metric_hash_map<thread_local_value<value_type>, N> value_map_;
dynamic_metric_hash_map<std::array<std::string, N>,
thread_local_value<value_type>>
value_map_;
size_t dupli_count_ = 2;
};

Expand Down
8 changes: 4 additions & 4 deletions include/ylt/metric/detail/ckms_quantiles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class CKMSQuantiles {
std::size_t idx = 0;
std::size_t item = idx++;

for (std::size_t i = start; i < buffer_count_; ++i) {
for (uint16_t i = start; i < buffer_count_; ++i) {
double v = buffer_[i];
while (idx < sample_.size() && sample_[item].value < v) {
item = idx++;
Expand Down Expand Up @@ -167,9 +167,9 @@ class CKMSQuantiles {
private:
const std::reference_wrapper<const std::vector<Quantile>> quantiles_;

std::size_t count_;
uint16_t count_;
std::vector<Item> sample_;
std::array<double, 500> buffer_;
std::size_t buffer_count_;
std::array<double, 200> buffer_;
uint16_t buffer_count_;
};
} // namespace ylt::metric
4 changes: 2 additions & 2 deletions include/ylt/metric/detail/time_window_quantiles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class TimeWindowQuantiles {

public:
TimeWindowQuantiles(const std::vector<CKMSQuantiles::Quantile>& quantiles,
Clock::duration max_age_seconds, int age_buckets)
Clock::duration max_age_seconds, uint16_t age_buckets)
: quantiles_(quantiles),
ckms_quantiles_(age_buckets, CKMSQuantiles(quantiles_)),
current_bucket_(0),
Expand Down Expand Up @@ -44,7 +44,7 @@ class TimeWindowQuantiles {

const std::vector<CKMSQuantiles::Quantile>& quantiles_;
mutable std::vector<CKMSQuantiles> ckms_quantiles_;
mutable std::size_t current_bucket_;
mutable uint16_t current_bucket_;

mutable Clock::time_point last_rotation_;
const Clock::duration rotation_interval_;
Expand Down
2 changes: 1 addition & 1 deletion include/ylt/metric/gauge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class basic_static_gauge : public basic_static_counter<value_type> {
using gauge_t = basic_static_gauge<int64_t>;
using gauge_d = basic_static_gauge<double>;

template <typename value_type, size_t N>
template <typename value_type, uint8_t N>
class basic_dynamic_gauge : public basic_dynamic_counter<value_type, N> {
using metric_t::set_metric_type;
using basic_dynamic_counter<value_type, N>::value_map_;
Expand Down
2 changes: 1 addition & 1 deletion include/ylt/metric/histogram.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class basic_static_histogram : public static_metric {
using histogram_t = basic_static_histogram<int64_t>;
using histogram_d = basic_static_histogram<double>;

template <typename value_type, size_t N>
template <typename value_type, uint8_t N>
class basic_dynamic_histogram : public dynamic_metric {
public:
basic_dynamic_histogram(std::string name, std::string help,
Expand Down
71 changes: 35 additions & 36 deletions include/ylt/metric/summary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,19 @@ class summary_t : public static_metric {
using Quantiles = std::vector<CKMSQuantiles::Quantile>;
summary_t(std::string name, std::string help, Quantiles quantiles,
std::chrono::milliseconds max_age = std::chrono::seconds{60},
int age_buckets = 5)
uint16_t age_buckets = 5)
: quantiles_{std::move(quantiles)},
static_metric(MetricType::Summary, std::move(name), std::move(help)),
max_age_(max_age),
age_buckets_(age_buckets) {
static_metric(MetricType::Summary, std::move(name), std::move(help)) {
init_no_label(max_age, age_buckets);
}

summary_t(std::string name, std::string help, Quantiles quantiles,
std::map<std::string, std::string> static_labels,
std::chrono::milliseconds max_age = std::chrono::seconds{60},
int age_buckets = 5)
uint16_t age_buckets = 5)
: quantiles_{std::move(quantiles)},
static_metric(MetricType::Summary, std::move(name), std::move(help),
std::move(static_labels)),
max_age_(max_age),
age_buckets_(age_buckets) {
std::move(static_labels)) {
init_no_label(max_age, age_buckets);
}

Expand Down Expand Up @@ -190,7 +186,7 @@ class summary_t : public static_metric {
});
}

void init_no_label(std::chrono::milliseconds max_age, int age_buckets) {
void init_no_label(std::chrono::milliseconds max_age, uint16_t age_buckets) {
init_block(block_);
block_->quantile_values_ =
std::make_shared<TimeWindowQuantiles>(quantiles_, max_age, age_buckets);
Expand Down Expand Up @@ -236,29 +232,33 @@ class summary_t : public static_metric {
std::shared_ptr<block_t> block_;
static inline std::shared_ptr<coro_io::io_context_pool> excutor_ =
coro_io::create_io_context_pool(1);
std::chrono::milliseconds max_age_;
int age_buckets_;
std::atomic<bool> is_coro_started_ = false;
};

template <size_t N>
template <uint8_t N>
struct summary_label_sample {
std::array<std::string, N> labels_value;
double value;
};

template <size_t N>
struct sum_and_count_t {
double sum;
uint64_t count;
};

template <uint8_t N>
struct labels_block_t {
std::atomic<bool> stop_ = false;
ylt::detail::moodycamel::ConcurrentQueue<summary_label_sample<N>>
sample_queue_;
dynamic_metric_hash_map<std::shared_ptr<TimeWindowQuantiles>, N>
dynamic_metric_hash_map<std::array<std::string, N>,
std::shared_ptr<TimeWindowQuantiles>>
label_quantile_values_;
dynamic_metric_hash_map<uint64_t, N> label_count_;
dynamic_metric_hash_map<double, N> label_sum_;
dynamic_metric_hash_map<std::array<std::string, N>, sum_and_count_t>
sum_and_count_;
};

template <size_t N>
template <uint8_t N>
class basic_dynamic_summary : public dynamic_metric {
public:
using Quantiles = std::vector<CKMSQuantiles::Quantile>;
Expand All @@ -267,7 +267,7 @@ class basic_dynamic_summary : public dynamic_metric {
std::string name, std::string help, Quantiles quantiles,
std::array<std::string, N> labels_name,
std::chrono::milliseconds max_age = std::chrono::seconds{60},
int age_buckets = 5)
uint16_t age_buckets = 5)
: quantiles_{std::move(quantiles)},
dynamic_metric(MetricType::Summary, std::move(name), std::move(help),
std::move(labels_name)),
Expand Down Expand Up @@ -300,6 +300,14 @@ class basic_dynamic_summary : public dynamic_metric {

size_t size_approx() { return labels_block_->sample_queue_.size_approx(); }

size_t label_value_count() override {
auto block = labels_block_;
return async_simple::coro::syncAwait(coro_io::post([block] {
return block->sum_and_count_.size();
}))
.value();
}

async_simple::coro::Lazy<std::vector<double>> get_rates(
const std::array<std::string, N> &labels_value, double &sum,
uint64_t &count) {
Expand All @@ -314,8 +322,8 @@ class basic_dynamic_summary : public dynamic_metric {
if (it == labels_block_->label_quantile_values_.end()) {
return;
}
sum = labels_block_->label_sum_[labels_value];
count = labels_block_->label_count_[labels_value];
sum = labels_block_->sum_and_count_[labels_value].sum;
count = labels_block_->sum_and_count_[labels_value].count;
for (const auto &quantile : quantiles_) {
vec.push_back(it->second->get(quantile.quantile));
}
Expand All @@ -325,15 +333,6 @@ class basic_dynamic_summary : public dynamic_metric {
co_return vec;
}

dynamic_metric_hash_map<double, N> value_map() {
auto ret = async_simple::coro::syncAwait(coro_io::post(
[this] {
return labels_block_->label_sum_;
},
excutor_->get_executor()));
return ret.value();
}

async_simple::coro::Lazy<void> serialize_async(std::string &str) override {
co_await serialize_async_with_label(str);
}
Expand Down Expand Up @@ -368,8 +367,8 @@ class basic_dynamic_summary : public dynamic_metric {

ptr->insert(sample.value);

label_block->label_count_[sample.labels_value] += 1;
label_block->label_sum_[sample.labels_value] += sample.value;
label_block->sum_and_count_[sample.labels_value].count += 1;
label_block->sum_and_count_[sample.labels_value].sum += sample.value;
index++;
if (index == count) {
break;
Expand Down Expand Up @@ -406,11 +405,11 @@ class basic_dynamic_summary : public dynamic_metric {

auto sum_map = co_await coro_io::post(
[this] {
return labels_block_->label_sum_;
return labels_block_->sum_and_count_;
},
excutor_->get_executor());

for (auto &[labels_value, sum_val] : sum_map.value()) {
for (auto &[labels_value, _] : sum_map.value()) {
double sum = 0;
uint64_t count = 0;
auto rates = co_await get_rates(labels_value, sum, count);
Expand Down Expand Up @@ -447,13 +446,13 @@ class basic_dynamic_summary : public dynamic_metric {

auto sum_map = co_await coro_io::post(
[this] {
return labels_block_->label_sum_;
return labels_block_->sum_and_count_;
},
excutor_->get_executor());

json_summary_t summary{name_, help_, std::string(metric_name())};

for (auto &[labels_value, sum_val] : sum_map.value()) {
for (auto &[labels_value, _] : sum_map.value()) {
json_summary_metric_t metric;
double sum = 0;
uint64_t count = 0;
Expand All @@ -478,7 +477,7 @@ class basic_dynamic_summary : public dynamic_metric {
static inline std::shared_ptr<coro_io::io_context_pool> excutor_ =
coro_io::create_io_context_pool(1);
std::chrono::milliseconds max_age_;
int age_buckets_;
uint16_t age_buckets_;
std::atomic<bool> is_coro_started_ = false;
};

Expand Down

0 comments on commit e21db0c

Please sign in to comment.