stasis-aries-wal/stasis/util/histogram.h
2010-09-30 19:28:42 +00:00

146 lines
5 KiB
C

/*
* histogram.h
*
* Created on: Sep 28, 2010
* Author: sears
*/
#ifndef HISTOGRAM_H_
#define HISTOGRAM_H_
#include <stasis/common.h>
#include <stdio.h>
#include <stasis/util/log2.h>
#include <stasis/util/time.h>
#define DECLARE_HISTOGRAM_64(x) \
stasis_histogram_64_t x; \
extern void stasis_histogram_ctor_##x() __attribute__((constructor)); \
void stasis_histogram_ctor_##x(void) { stasis_histogram_64_clear(&x); \
stasis_auto_histogram_count++; \
stasis_auto_histograms = realloc(stasis_auto_histograms, sizeof(void*)*stasis_auto_histogram_count); \
stasis_auto_histogram_names = realloc(stasis_auto_histogram_names, sizeof(void*)*stasis_auto_histogram_count); \
stasis_auto_histograms[stasis_auto_histogram_count - 1] = &x; \
stasis_auto_histogram_names[stasis_auto_histogram_count - 1] = __FILE__":"#x; \
}
// extern void stasis_histogram_dtor_##x() __attribute__((destructor));
// void stasis_histogram_dtor_##x(void) { /*printf("%s: Histogram %s\n", __FILE__, #x);*/
// stasis_histogram_pretty_print_64(&x); }
typedef struct {
uint64_t buckets[64];
} stasis_histogram_64_t;
extern stasis_histogram_64_t**stasis_auto_histograms;
extern char** stasis_auto_histogram_names;
extern int stasis_auto_histogram_count;
typedef struct {
uint64_t buckets[32];
} stasis_histogram_32_t;
static inline void stasis_histogram_64_clear(stasis_histogram_64_t * hist) {
for(int i = 0; i < 64; i++) { hist->buckets[i] = 0; }
}
static inline void stasis_histogram_32_clear(stasis_histogram_32_t * hist) {
for(int i = 0; i < 32; i++) { hist->buckets[i] = 0; }
}
static inline void stasis_histogram_insert_log_uint64_t(stasis_histogram_64_t* hist, uint64_t val) {
hist->buckets[stasis_log_2_64(val)]++;
}
static inline void stasis_histogram_insert_log_uint32_t(stasis_histogram_32_t* hist, uint64_t val) {
hist->buckets[stasis_log_2_32(val)]++;
}
static inline void stasis_histogram_insert_log_timeval(stasis_histogram_64_t* hist, const struct timeval val) {
hist->buckets[stasis_log_2_timeval(val)]++;
}
static inline uint64_t stasis_histogram_earth_movers_distance_64(stasis_histogram_64_t* a, stasis_histogram_64_t* b) {
double moved_so_far = 0.0;
double in_shovel = 0.0;
double a_mass = 0.0, b_mass = 0.0;
for(int i = 0; i < 64; i++) {
a_mass += ((double)a->buckets[i]);
b_mass += ((double)b->buckets[i]);
}
if(a_mass == 0.0 || b_mass == 0.0) { return (uint64_t)-1; }
for(int i = 0; i < 64; i++) {
in_shovel += (b_mass * (double)a->buckets[i]) - ((double)b->buckets[i]);
moved_so_far += (in_shovel >= 0 ? in_shovel : -in_shovel);
}
return moved_so_far / a_mass;
}
static inline uint64_t stasis_histogram_earth_movers_distance_32(stasis_histogram_32_t* a, stasis_histogram_32_t* b) {
double moved_so_far = 0.0;
double in_shovel = 0.0;
double a_mass = 0.0, b_mass = 0.0;
for(int i = 0; i < 32; i++) {
a_mass += ((double)stasis_log_2_64(a->buckets[i]));
b_mass += ((double)stasis_log_2_64(b->buckets[i]));
}
if(a_mass == 0.0 || b_mass == 0.0) { return (uint64_t)-1; }
for(int i = 0; i < 32; i++) {
in_shovel += (b_mass * (double)stasis_log_2_64(a->buckets[i])) - ((double)stasis_log_2_64(b->buckets[i]));
moved_so_far += (in_shovel >= 0 ? in_shovel : -in_shovel);
}
return moved_so_far / a_mass;
}
void stasis_histogram_pretty_print_64(stasis_histogram_64_t* a);
void stasis_histogram_pretty_print_32(stasis_histogram_32_t* a);
void stasis_histograms_auto_dump(void);
#endif /* HISTOGRAM_H_ */
void stasis_histogram_pretty_print_64(stasis_histogram_64_t* a) {
uint8_t logs[64];
int max_log = 0;
for(int i = 0; i < 64; i++) {
logs[i] = stasis_log_2_64(a->buckets[i]);
if(logs[i] > max_log) { max_log = logs[i]; }
}
for(int i = max_log; i > 0; i--) {
if(!(i % 10)) {
printf("2^%2d ", i);
} else {
printf(" ");
}
for(int j = 0; j < 64; j++) {
printf(logs[j] >= i ? "#" : " ");
}
printf("\n");
}
if(max_log == 0) {
printf("[empty]\n");
} else {
printf(" us ms s ks Ms\n");
}
}
void stasis_histogram_pretty_print_32(stasis_histogram_32_t* a) {
uint8_t logs[32];
int max_log = 0;
for(int i = 0; i < 32; i++) {
logs[i] = stasis_log_2_64(a->buckets[i]);
if(logs[i] > max_log) { max_log = logs[i]; }
}
for(int i = max_log; i >= 0; i--) {
if(!(i % 10)) {
printf("2^%2d ", i);
} else {
printf(" ");
}
for(int j = 0; j < 32; j++) {
printf(logs[j] >= i ? "#" : " ");
}
printf("\n");
}
if(max_log == 0) {
printf("[empty]\n");
} else {
//01234567890123456789012345678901234567890
printf(" us ms s ks Ms\n");
}
}