The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

/*
* File: ms_stats.h
* Author: Mingqiang Zhuang
*
* Created on March 25, 2009
*
* (c) Copyright 2009, Schooner Information Technology, Inc.
*
*/
#include "mem_config.h"
#include <inttypes.h>
#include "ms_stats.h"
#define array_size(x) (sizeof(x) / sizeof((x)[0]))
static int ms_local_log2(uint64_t value);
static uint64_t ms_get_events(ms_stat_t *stat);
/**
* get the index of local log2 array
*
* @param value
*
* @return return the index of local log2 array
*/
static int ms_local_log2(uint64_t value)
{
int result= 0;
while (result <= 63 && ((uint64_t)1 << result) < value)
{
result++;
}
return result;
} /* ms_local_log2 */
/**
* initialize statistic structure
*
* @param stat, pointer of the statistic structure
* @param name, name of the statistic
*/
void ms_init_stats(ms_stat_t *stat, const char *name)
{
memset(stat, 0, sizeof(*stat));
stat->name= (char *)name;
stat->min_time= (uint64_t)-1;
stat->max_time= 0;
stat->period_min_time= (uint64_t)-1;
stat->period_max_time= 0;
stat->log_product= 0;
stat->total_time= 0;
stat->pre_total_time= 0;
stat->squares= 0;
stat->pre_squares= 0;
stat->pre_events= 0;
stat->pre_log_product= 0;
stat->get_miss= 0;
stat->pre_get_miss= 0;
} /* ms_init_stats */
/**
* record one event
*
* @param stat, pointer of the statistic structure
* @param total_time, response time of the command
* @param get_miss, whether it gets miss
*/
void ms_record_event(ms_stat_t *stat, uint64_t total_time, int get_miss)
{
stat->total_time+= total_time;
if (total_time < stat->min_time)
{
stat->min_time= total_time;
}
if (total_time > stat->max_time)
{
stat->max_time= total_time;
}
if (total_time < stat->period_min_time)
{
stat->period_min_time= total_time;
}
if (total_time > stat->period_max_time)
{
stat->period_max_time= total_time;
}
if (get_miss)
{
stat->get_miss++;
}
stat->dist[ms_local_log2(total_time)]++;
stat->squares+= (double)(total_time * total_time);
if (total_time != 0)
{
stat->log_product+= log((double)total_time);
}
} /* ms_record_event */
/**
* get the events count
*
* @param stat, pointer of the statistic structure
*
* @return total events recorded
*/
static uint64_t ms_get_events(ms_stat_t *stat)
{
uint64_t events= 0;
for (uint32_t i= 0; i < array_size(stat->dist); i++)
{
events+= stat->dist[i];
}
return events;
} /* ms_get_events */
/**
* dump the statistics
*
* @param stat, pointer of the statistic structure
*/
void ms_dump_stats(ms_stat_t *stat)
{
uint64_t events= 0;
int max_non_zero= 0;
int min_non_zero= 0;
double average= 0;
for (uint32_t i= 0; i < array_size(stat->dist); i++)
{
events+= stat->dist[i];
if (stat->dist[i] != 0)
{
max_non_zero= (int)i;
}
}
if (events == 0)
{
return;
}
average= (double)(stat->total_time / events);
printf("%s Statistics (%lld events)\n", stat->name, (long long)events);
printf(" Min: %8lld\n", (long long)stat->min_time);
printf(" Max: %8lld\n", (long long)stat->max_time);
printf(" Avg: %8lld\n", (long long)(stat->total_time / events));
printf(" Geo: %8.2lf\n", exp(stat->log_product / (double)events));
if (events > 1)
{
printf(" Std: %8.2lf\n",
sqrt((stat->squares - (double)events * average
* average) / ((double)events - 1)));
}
printf(" Log2 Dist:");
for (int i= 0; i <= max_non_zero - 4; i+= 4)
{
if ((stat->dist[i + 0] != 0)
|| (stat->dist[i + 1] != 0)
|| (stat->dist[i + 2] != 0)
|| (stat->dist[i + 3] != 0))
{
min_non_zero= i;
break;
}
}
for (int i= min_non_zero; i <= max_non_zero; i++)
{
if ((i % 4) == 0)
{
printf("\n %2d:", (int)i);
}
printf(" %6" PRIu64 , stat->dist[i]);
}
printf("\n\n");
} /* ms_dump_stats */
/**
* dump the format statistics
*
* @param stat, pointer of the statistic structure
* @param run_time, the total run time
* @param freq, statistic frequency
* @param obj_size, average object size
*/
void ms_dump_format_stats(ms_stat_t *stat,
int run_time,
int freq,
int obj_size)
{
uint64_t events= 0;
double global_average= 0;
uint64_t global_tps= 0;
double global_rate= 0;
double global_std= 0;
double global_log= 0;
double period_average= 0;
uint64_t period_tps= 0;
double period_rate= 0;
double period_std= 0;
double period_log= 0;
if ((events= ms_get_events(stat)) == 0)
{
return;
}
global_average= (double)(stat->total_time / events);
global_tps= events / (uint64_t)run_time;
global_rate= (double)events * obj_size / 1024 / 1024 / run_time;
global_std= sqrt((stat->squares - (double)events * global_average
* global_average) / (double)(events - 1));
global_log= exp(stat->log_product / (double)events);
uint64_t diff_time= stat->total_time - stat->pre_total_time;
uint64_t diff_events= events - stat->pre_events;
if (diff_events >= 1)
{
period_average= (double)(diff_time / diff_events);
period_tps= diff_events / (uint64_t)freq;
period_rate= (double)diff_events * obj_size / 1024 / 1024 / freq;
double diff_squares= (double)stat->squares - (double)stat->pre_squares;
period_std= sqrt((diff_squares - (double)diff_events * period_average
* period_average) / (double)(diff_events - 1));
double diff_log_product= stat->log_product - stat->pre_log_product;
period_log= exp(diff_log_product / (double)diff_events);
}
printf("%s Statistics\n", stat->name);
printf("%-8s %-8s %-12s %-12s %-10s %-10s %-8s %-10s %-10s %-10s %-10s\n",
"Type",
"Time(s)",
"Ops",
"TPS(ops/s)",
"Net(M/s)",
"Get_miss",
"Min(us)",
"Max(us)",
"Avg(us)",
"Std_dev",
"Geo_dist");
printf(
"%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n",
"Period",
freq,
(long long)diff_events,
(long long)period_tps,
global_rate,
(long long)(stat->get_miss - stat->pre_get_miss),
(long long)stat->period_min_time,
(long long)stat->period_max_time,
(long long)period_average,
period_std,
period_log);
printf(
"%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n\n",
"Global",
run_time,
(long long)events,
(long long)global_tps,
period_rate,
(long long)stat->get_miss,
(long long)stat->min_time,
(long long)stat->max_time,
(long long)global_average,
global_std,
global_log);
stat->pre_events= events;
stat->pre_squares= (uint64_t)stat->squares;
stat->pre_total_time= stat->total_time;
stat->pre_log_product= stat->log_product;
stat->period_min_time= (uint64_t)-1;
stat->period_max_time= 0;
stat->pre_get_miss= stat->get_miss;
} /* ms_dump_format_stats */