static void load_histograms() { int i; if (raw_histogram) { free(raw_histogram); } hdr_alloc(3600L * 1000 * 1000, 3, &raw_histogram); if (cor_histogram) { free(cor_histogram); } hdr_alloc(3600L * 1000 * 1000, 3, &cor_histogram); for (i = 0; i < 10000; i++) { hdr_record_value(raw_histogram, 1000L); hdr_record_corrected_value(cor_histogram, 1000L, 10000L); } hdr_record_value(raw_histogram, 100000000L); hdr_record_corrected_value(cor_histogram, 100000000L, 10000L); }
static void load_histograms() { const int64_t highest_trackable_value = 3600L * 1000 * 1000; const int32_t significant_figures = 3; const int64_t interval = 10000L; const int64_t scale = 512; const int64_t scaled_interval = interval * scale; int i; if (raw_histogram) { free(raw_histogram); } hdr_alloc(highest_trackable_value, significant_figures, &raw_histogram); if (cor_histogram) { free(cor_histogram); } hdr_alloc(highest_trackable_value, significant_figures, &cor_histogram); if (scaled_raw_histogram) { free(scaled_raw_histogram); } hdr_init(1000, highest_trackable_value * 512, significant_figures, &scaled_raw_histogram); if (scaled_cor_histogram) { free(scaled_cor_histogram); } hdr_init(1000, highest_trackable_value * 512, significant_figures, &scaled_cor_histogram); for (i = 0; i < 10000; i++) { hdr_record_value(raw_histogram, 1000L); hdr_record_corrected_value(cor_histogram, 1000L, interval); hdr_record_value(scaled_raw_histogram, 1000L * scale); hdr_record_corrected_value(scaled_cor_histogram, 1000L * scale, scaled_interval); } hdr_record_value(raw_histogram, 100000000L); hdr_record_corrected_value(cor_histogram, 100000000L, 10000L); hdr_record_value(scaled_raw_histogram, 100000000L * scale); hdr_record_corrected_value(scaled_cor_histogram, 100000000L * scale, scaled_interval); }
static char* test_invalid_significant_figures() { struct hdr_histogram* h = NULL; int r = hdr_alloc(36000000, -1, &h); mu_assert("Result was not EINVAL", r == EINVAL); mu_assert("Histogram was not null", h == 0); r = hdr_alloc(36000000, 6, &h); mu_assert("Result was not EINVAL", r == EINVAL); mu_assert("Histogram was not null", h == 0); return 0; }
int main(int argc, char **argv) { struct hdr_histogram* histogram; int64_t max_value = 24 * 60 * 60 * 1000000L; int result = hdr_alloc(max_value, 4, &histogram); if (result != 0) { fprintf(stderr, "Failed to allocate histogram: %d\n", result); return -1; } struct timespec t0; struct timespec t1; setlocale(LC_NUMERIC, ""); int64_t iterations = 400000000; for (int i = 0; i < 100; i++) { clock_gettime(CLOCK_MONOTONIC_RAW, &t0); for (int64_t j = 1; j < iterations; j++) { hdr_record_value(histogram, j); } clock_gettime(CLOCK_MONOTONIC_RAW, &t1); struct timespec taken = diff(t0, t1); double time_taken = taken.tv_sec + taken.tv_nsec / 1000000000.0; double ops_sec = (iterations - 1) / time_taken; printf("%s - %d, ops/sec: %'.2f\n", "Iteration", i + 1, ops_sec); } return 0; }
static void load_histograms() { free(raw_histogram); free(cor_histogram); hdr_alloc(INT64_C(3600) * 1000 * 1000, 3, &raw_histogram); hdr_alloc(INT64_C(3600) * 1000 * 1000, 3, &cor_histogram); for (int i = 0; i < 10000; i++) { hdr_record_value(raw_histogram, 1000); hdr_record_corrected_value(cor_histogram, 1000, 10000); } hdr_record_value(raw_histogram, 100000000); hdr_record_corrected_value(cor_histogram, 100000000, 10000); }
int main(int argc, char **argv) { int i; struct hdr_histogram* raw_histogram = NULL; struct hdr_histogram* cor_histogram = NULL; hdr_alloc(100000000, 3, &raw_histogram); hdr_alloc(100000000, 3, &cor_histogram); for (i = 0; i < 10000; i++) { hdr_record_value(raw_histogram, 1000L); hdr_record_corrected_value(cor_histogram, 1000L, 10000L); } hdr_record_value(raw_histogram, 100000000L); hdr_record_corrected_value(cor_histogram, 100000000L, 10000L); hdr_percentiles_print(raw_histogram, stdout, 5, 1.0, CSV); hdr_percentiles_print(cor_histogram, stdout, 5, 1.0, CSV); }
static char* test_create() { struct hdr_histogram* h = NULL; int r = hdr_alloc(36000000, 4, &h); size_t s = hdr_get_memory_size(h); mu_assert("Failed to allocate hdr_histogram", r == 0); mu_assert("Failed to allocate hdr_histogram", h != NULL); mu_assert("Size is incorrect", s == 1704008); free(h); return 0; }
ERL_NIF_TERM _hh_rotate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { hh_ctx_t* ctx = NULL; hh_ctx_t* to = NULL; ErlNifBinary target; ErlNifResourceType* ctx_type = get_hh_ctx_type(env); if (argc != 2 || ctx_type == NULL || !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) || ctx->data == NULL || !enif_get_resource(env, argv[1], ctx_type, (void **)&to) || to->data == NULL) { return enif_make_badarg(env); } hdr_histogram_t* diff_histogram; int rc = 0; rc = hdr_alloc(ctx->highest_trackable_value, ctx->significant_figures, &diff_histogram); if (ENOMEM == rc) { return make_error(env, "not_enough_memory"); } hdr_rotate(ctx->data, to->data, diff_histogram); int size = 0; uint8_t* data = NULL; int success = hdr_encode_uncompressed(diff_histogram, &data, &size); if (!enif_alloc_binary(size, &target)) { return make_error(env, "bad_hdr_binary_alloc"); } target.size = size; memcpy(target.data, data, size); free(data); free(diff_histogram); if (success != 0) { return make_error(env, "bad_hdr_binary"); } return enif_make_binary(env, &target); }
static char* test_encode_decode_empty() { struct hdr_histogram *histogram, *hdr_new = NULL; hdr_alloc(INT64_C(3600) * 1000 * 1000, 3, &histogram); char *data; mu_assert("Failed to encode histogram data", hdr_log_encode(histogram, &data) == 0); mu_assert("Failed to decode histogram data", hdr_log_decode(&hdr_new, data, strlen(data)) == 0); mu_assert("Histograms should be the same", compare_histogram(histogram, hdr_new)); // mu_assert("Mean different after encode/decode", compare_double(hdr_mean(histogram), hdr_mean(hdr_new), 0.001)); free(histogram); free(hdr_new); free(data); return 0; }
static char* test_string_encode_decode() { struct hdr_histogram *histogram, *hdr_new = NULL; hdr_alloc(INT64_C(3600) * 1000 * 1000, 3, &histogram); for (int i = 1; i < 100; i++) { hdr_record_value(histogram, i*i); } char *data; mu_assert("Failed to encode histogram data", hdr_log_encode(histogram, &data) == 0); mu_assert("Failed to decode histogram data", hdr_log_decode(&hdr_new, data, strlen(data)) == 0); mu_assert("Histograms should be the same", compare_histogram(histogram, hdr_new)); mu_assert("Mean different after encode/decode", compare_double(hdr_mean(histogram), hdr_mean(hdr_new), 0.001)); return 0; }
static char* test_string_encode_decode_2() { struct hdr_histogram *histogram, *hdr_new = NULL; hdr_alloc(1000, 3, &histogram); int i; for (i = 1; i < histogram->highest_trackable_value; i++) { hdr_record_value(histogram, i); } char *data; mu_assert( "Failed to encode histogram data", validate_return_code(hdr_log_encode(histogram, &data))); mu_assert( "Failed to decode histogram data", validate_return_code(hdr_log_decode(&hdr_new, data, strlen(data)))); mu_assert("Histograms should be the same", compare_histogram(histogram, hdr_new)); mu_assert("Mean different after encode/decode", compare_double(hdr_mean(histogram), hdr_mean(hdr_new), 0.001)); return 0; }
ERL_NIF_TERM _hh_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { long highest_trackable_value = 0; int significant_figures = 0; if (argc != 2 || !enif_get_int64(env, argv[0], &highest_trackable_value) || !enif_get_int(env, argv[1], &significant_figures)) { return enif_make_badarg(env); } hdr_histogram_t* raw_histogram; int rc = 0; rc = hdr_alloc(highest_trackable_value, significant_figures, &raw_histogram); if (EINVAL == rc) { return make_error(env, "bad_significant_factor"); } if (ENOMEM == rc) { return make_error(env, "not_enough_memory"); } ErlNifResourceType* ctx_type = get_hh_ctx_type(env); hh_ctx_t* ctx = (hh_ctx_t*)enif_alloc_resource(ctx_type, sizeof(hh_ctx_t)); ctx->data = raw_histogram; ctx->highest_trackable_value = highest_trackable_value; ctx->significant_figures = significant_figures; ERL_NIF_TERM result = enif_make_resource(env, ctx); enif_release_resource(ctx); return enif_make_tuple2(env, ATOM_OK, result); }
static char* log_reader_aggregates_into_single_histogram() { const char* file_name = "histogram.log"; hdr_timespec timestamp; hdr_timespec interval; hdr_gettime(×tamp); interval.tv_sec = 5; interval.tv_nsec = 2000000; struct hdr_log_writer writer; struct hdr_log_reader reader; hdr_log_writer_init(&writer); hdr_log_reader_init(&reader); int rc = 0; FILE* log_file = fopen(file_name, "w+"); hdr_log_write_header(&writer, log_file, "Test log", ×tamp); hdr_log_write(&writer, log_file, ×tamp, &interval, cor_histogram); hdr_log_write(&writer, log_file, ×tamp, &interval, raw_histogram); fflush(log_file); fclose(log_file); log_file = fopen(file_name, "r"); struct hdr_histogram* histogram; hdr_alloc(INT64_C(3600) * 1000 * 1000, 3, &histogram); rc = hdr_log_read_header(&reader, log_file); mu_assert("Failed header read", validate_return_code(rc)); rc = hdr_log_read(&reader, log_file, &histogram, NULL, NULL); mu_assert("Failed corrected read", validate_return_code(rc)); rc = hdr_log_read(&reader, log_file, &histogram, NULL, NULL); mu_assert("Failed raw read", validate_return_code(rc)); struct hdr_iter iter; hdr_iter_recorded_init(&iter, histogram); int64_t expected_total_count = raw_histogram->total_count + cor_histogram->total_count; mu_assert( "Total counts incorrect", compare_int64(histogram->total_count, expected_total_count)); while (hdr_iter_next(&iter)) { int64_t count = iter.count; int64_t value = iter.value; int64_t expected_count = hdr_count_at_value(raw_histogram, value) + hdr_count_at_value(cor_histogram, value); mu_assert("Incorrect count", compare_int64(count, expected_count)); } fclose(log_file); remove(file_name); free(histogram); return 0; }
int main ( int argc, char *argv[] ) { unsigned long int microdelta, interval_length, interval_diff, sample_desired_wait_time; int nfds,return_value, delay_microseconds, run_seconds, total_runtime_seconds; int fd, opt, quit=0; char buffer[128]; char identifier[IDENTIFIER_SIZE]; struct pollfd poll_list[256]; struct itimerspec timeout; struct timespec sample_start_time, sample_end_time, interval_start; struct timeval end; struct hdr_histogram *interval_histogram, *cumulative_histogram; // 10 seconds worth of microseconds if (hdr_alloc(10000000, 3, &interval_histogram) == -1) { printf("unable to allocate interval histogram\n"); exit (1); } if (hdr_alloc(10000000, 3, &cumulative_histogram) == -1) { printf("unable to allocate cumulative histogram\n"); exit (1); } memset (buffer, 0, 128); memset (identifier, 0, IDENTIFIER_SIZE); // Timing and names // // interval_length - this is the length of time between successive histogram line printouts // // sample_desired_wait_time - this is the amount of time we set the timer to wait for. This should be // less than the jitter we're attempting to measure. Given the nature of this // program, this should always be less than 1 second. If it is not, you'll need to // modify the code below where we set the interval timer. // sample_start_time, // sample_end_time - The times associated with a single pass through the timing loop. // // delay_microseconds - An arbitrary amount of time we wait before starting anything. This is useful if // you want to catch something, and there's a warm up period. // For compatibility with jHiccup this is specified on the command line as millis. // // run_seconds - The time we spend running the timing loops. // interval_length = 5; // 5 seconds per reporting interval sample_desired_wait_time = 1000000; // 1 millisecond in nanoseconds. delay_microseconds = 0; run_seconds = 100000000; // forever, or near enough - 3 years. while ( (opt = getopt(argc, argv, "d:l:r:vh")) != -1) { switch (opt) { case 'd': delay_microseconds = atoi(optarg) * 1000; break; case 'l': strncpy(identifier, optarg, IDENTIFIER_SIZE-1); break; case 'r': run_seconds = atoi(optarg); break; case 'v': verbose_flag = 1; break; case 'h': default: usage(); exit(-1); } } total_runtime_seconds = run_seconds + (delay_microseconds/1000000); open_files(identifier); if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC)) < 0) { perror("timerfd_create; failed to create timer"); return -1; } zero_timeout(&timeout); interval_length = interval_length * 1000000000; // convert to nanoseconds // set up the poll list structure. memset (&poll_list, 0, (256*sizeof(struct pollfd))); poll_list[0].fd=fd; poll_list[0].events=POLLIN|POLLPRI|POLLRDHUP; poll_list[0].revents=0; nfds = 1; // get wall clock start time and push out a header gettimeofday(&start,NULL); print_header_line(log_file, &start); if (verbose_flag) print_header_line(stdout, &start); // we wait a set number of seconds before starting the test. usleep(delay_microseconds); // get start of our delta interval measurement clock_gettime(CLOCK_MONOTONIC, &interval_start); while (!quit) { timeout.it_value.tv_sec = 0; timeout.it_value.tv_nsec = sample_desired_wait_time; // We arm the timer first (timerfd_settime), then get the time as quickly as possible. // We don't want to measure the time that timerfd_settime takes, so its a choice between // under or over reporting the time, as clock_gettime is expected to be fast. timerfd_settime(fd, 0, &timeout, NULL); clock_gettime(CLOCK_MONOTONIC,&sample_start_time); return_value = poll(poll_list,nfds,-1); clock_gettime(CLOCK_MONOTONIC,&sample_end_time); // the the error value is anything other than EINTR we have a real problem. if ((return_value < 0) && (errno != EINTR)) { perror("poll problem"); exit(-1); } // read the timer to clear the event. read(fd,buffer,8); // record the delta for both the interval and cumulative histograms. microdelta = nano_difftime(sample_start_time, sample_end_time)/1000; hdr_record_value(interval_histogram, microdelta); hdr_record_value(cumulative_histogram, microdelta); // See if we're due to print out an interval update. interval_diff = nano_difftime(interval_start, sample_end_time); if (interval_diff >= interval_length) { // print progress print_histogram_line(log_file, interval_histogram, cumulative_histogram); if (verbose_flag) print_histogram_line(stdout, interval_histogram, cumulative_histogram); print_full_histogram(histogram_file,cumulative_histogram); // are we done? gettimeofday(&end, NULL); if (end.tv_sec >= (start.tv_sec + total_runtime_seconds)) quit++; // reset the interval histogram. hdr_reset(interval_histogram); // reset the interval start timer. clock_gettime(CLOCK_MONOTONIC, &interval_start); } } close(fd); exit (0); }