Skip to content

Commit

Permalink
Revert LATENCY_HDR_SEC_SIGDIGTS to 2. Optimize summarize_current_seco…
Browse files Browse the repository at this point in the history
…nd by using hdr_value_at_percentiles() instead of N x hdr_value_at_percentile(). (#295)
  • Loading branch information
filipecosta90 authored Jan 29, 2025
1 parent ae4c12b commit 9095d98
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 21 deletions.
Empty file added deps/hdr_histogram/.dirstamp
Empty file.
59 changes: 49 additions & 10 deletions deps/hdr_histogram/hdr_histogram.c
Original file line number Diff line number Diff line change
Expand Up @@ -643,28 +643,67 @@ int64_t hdr_min(const struct hdr_histogram* h)
return non_zero_min(h);
}

static int64_t get_value_from_idx_up_to_count(const struct hdr_histogram* h, int64_t count_at_percentile)
{
int64_t count_to_idx = 0;

count_at_percentile = 0 < count_at_percentile ? count_at_percentile : 1;
for (int32_t idx = 0; idx < h->counts_len; idx++)
{
count_to_idx += h->counts[idx];
if (count_to_idx >= count_at_percentile)
{
return hdr_value_at_index(h, idx);
}
}

return 0;
}

int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile)
{
struct hdr_iter iter;
int64_t total = 0;
double requested_percentile = percentile < 100.0 ? percentile : 100.0;
int64_t count_at_percentile =
(int64_t) (((requested_percentile / 100) * h->total_count) + 0.5);
count_at_percentile = count_at_percentile > 1 ? count_at_percentile : 1;
int64_t value_from_idx = get_value_from_idx_up_to_count(h, count_at_percentile);
if (percentile == 0.0)
{
return lowest_equivalent_value(h, value_from_idx);
}
return highest_equivalent_value(h, value_from_idx);
}

hdr_iter_init(&iter, h);
int hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length)
{
if (NULL == percentiles || NULL == values)
{
return EINVAL;
}

while (hdr_iter_next(&iter))
struct hdr_iter iter;
const int64_t total_count = h->total_count;
// to avoid allocations we use the values array for intermediate computation
// i.e. to store the expected cumulative count at each percentile
for (size_t i = 0; i < length; i++)
{
total += iter.count;
const double requested_percentile = percentiles[i] < 100.0 ? percentiles[i] : 100.0;
const int64_t count_at_percentile =
(int64_t) (((requested_percentile / 100) * total_count) + 0.5);
values[i] = count_at_percentile > 1 ? count_at_percentile : 1;
}

if (total >= count_at_percentile)
hdr_iter_init(&iter, h);
int64_t total = 0;
size_t at_pos = 0;
while (hdr_iter_next(&iter) && at_pos < length)
{
total += iter.count;
while (at_pos < length && total >= values[at_pos])
{
int64_t value_from_index = iter.value;
return highest_equivalent_value(h, value_from_index);
values[at_pos] = highest_equivalent_value(h, iter.value);
at_pos++;
}
}

return 0;
}

Expand Down
12 changes: 12 additions & 0 deletions deps/hdr_histogram/hdr_histogram.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,18 @@ int64_t hdr_max(const struct hdr_histogram* h);
*/
int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile);

/**
* Get the values at the given percentiles.
*
* @param h "This" pointer.
* @param percentiles The ordered percentiles array to get the values for.
* @param length Number of elements in the arrays.
* @param values Destination array containing the values at the given percentiles.
* The values array should be allocated by the caller.
* @return 0 on success, ENOMEM if the provided destination array is null.
*/
int hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length);

/**
* Gets the standard deviation for the values in the histogram.
*
Expand Down
7 changes: 4 additions & 3 deletions run_stats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ run_stats::run_stats(benchmark_config *config) :
{
memset(&m_start_time, 0, sizeof(m_start_time));
memset(&m_end_time, 0, sizeof(m_end_time));
quantiles_list = config->print_percentiles.quantile_list;

std::vector<float> quantiles_list_float = config->print_percentiles.quantile_list;
std::sort(quantiles_list_float.begin(), quantiles_list_float.end());
quantiles_list = std::vector<double>(quantiles_list_float.begin(), quantiles_list_float.end());
if (config->arbitrary_commands->is_defined()) {
setup_arbitrary_commands(config->arbitrary_commands->size());
}
Expand Down Expand Up @@ -882,7 +883,7 @@ void run_stats::summarize(totals& result) const
void result_print_to_json(json_handler * jsonhandler, const char * type, double ops_sec,
double hits, double miss, double moved, double ask, double kbs, double kbs_rx, double kbs_tx,
double latency, long m_total_latency, long ops,
std::vector<float> quantile_list, struct hdr_histogram* latency_histogram,
std::vector<double> quantile_list, struct hdr_histogram* latency_histogram,
std::vector<unsigned int> timestamps,
std::vector<one_sec_cmd_stats> timeserie_stats )
{
Expand Down
2 changes: 1 addition & 1 deletion run_stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class run_stats {
totals m_totals;

std::list<one_second_stats> m_stats;
std::vector<float> quantiles_list;
std::vector<double> quantiles_list;

// current second stats ( appended to m_stats and reset every second )
one_second_stats m_cur_stats;
Expand Down
13 changes: 8 additions & 5 deletions run_stats_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,14 @@ void one_sec_cmd_stats::merge(const one_sec_cmd_stats& other) {
m_min_latency = other.m_min_latency < m_min_latency ? other.m_min_latency : m_min_latency;
}

void one_sec_cmd_stats::summarize_quantiles(safe_hdr_histogram histogram, std::vector<float> quantiles) {
for (std::size_t i = 0; i < quantiles.size(); i++){
const float quantile = quantiles[i];
const double value = hdr_value_at_percentile(histogram, quantile)/ (double) LATENCY_HDR_RESULTS_MULTIPLIER;
summarized_quantile_values.push_back(value);
void one_sec_cmd_stats::summarize_quantiles(safe_hdr_histogram histogram, std::vector<double> sorted_quantiles) {
std::vector<int64_t> values(sorted_quantiles.size());
int result = hdr_value_at_percentiles(histogram, sorted_quantiles.data(), values.data(), sorted_quantiles.size());
if (result != 0) {
return;
}
for (std::size_t i = 0; i < sorted_quantiles.size(); i++) {
summarized_quantile_values.push_back(values[i] / static_cast<double>(LATENCY_HDR_RESULTS_MULTIPLIER));
}
}

Expand Down
11 changes: 9 additions & 2 deletions run_stats_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#define LATENCY_HDR_SIGDIGTS 3
#define LATENCY_HDR_SEC_MIN_VALUE 10
#define LATENCY_HDR_SEC_MAX_VALUE 600000000 ## LL
#define LATENCY_HDR_SEC_SIGDIGTS 3
#define LATENCY_HDR_SEC_SIGDIGTS 2
#define LATENCY_HDR_RESULTS_MULTIPLIER 1000
#define LATENCY_HDR_GRANULARITY 10

Expand Down Expand Up @@ -90,7 +90,14 @@ class one_sec_cmd_stats {
one_sec_cmd_stats();
void reset();
void merge(const one_sec_cmd_stats& other);
void summarize_quantiles(safe_hdr_histogram histogram, std::vector<float> quantiles);
/**
* Summarizes quantiles from the given histogram.
*
* @param histogram The histogram from which quantile values are extracted.
* @param sorted_quantiles A sorted (ascending order) vector of quantiles for which values will be computed.
* The caller must ensure the vector is sorted from smallest to largest.
*/
void summarize_quantiles(safe_hdr_histogram histogram, std::vector<double> sorted_quantiles);
void update_op(unsigned int bytes_rx, unsigned int bytes_tx, unsigned int latency);
void update_op(unsigned int bytes_rx, unsigned int bytes_tx, unsigned int latency, unsigned int hits, unsigned int misses);
void update_moved_op(unsigned int bytes_rx, unsigned int bytes_tx, unsigned int latency);
Expand Down

0 comments on commit 9095d98

Please sign in to comment.