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); }
void stats_record(stats *stats, uint64_t x) { if (x < stats->min) stats->min = x; if (x > stats->max) stats->max = x; if (stats->histogram != NULL) { hdr_record_value(stats->histogram, x); return; } stats->data[stats->index++] = x; if (stats->limit < stats->samples) stats->limit++; if (stats->index == stats->samples) stats->index = 0; }
int process_msg(struct msghdr *msg, char *buffer, struct hdr_histogram *hist) { struct timeval tx_timestamp; struct timeval rx_timestamp; int tx_rx = 0; for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { switch (cmsg->cmsg_level) { case SOL_SOCKET: switch (cmsg->cmsg_type) { case SO_TIMESTAMPNS: { struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg); rx_timestamp.tv_sec = stamp->tv_sec; rx_timestamp.tv_usec = stamp->tv_nsec / 1000; tx_rx += 1; break; } default: break; } case IPPROTO_IP: if (pktgen_packet(buffer, &tx_timestamp)) { tx_rx += 1; break; } else { return 0; } default: break; } } if (tx_rx == 2) { uint64_t latency = ((rx_timestamp.tv_sec - tx_timestamp.tv_sec) / 1000000) + (rx_timestamp.tv_usec - tx_timestamp.tv_usec); hdr_record_value(hist, latency); return 1; } 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; }
int main(int argc, char **argv) { struct hdr_histogram* histogram; int64_t max_value = 24 * 60 * 60 * 1000000L; int64_t min_value = 1; int result = -1; result = hdr_init(min_value, 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++) { hdr_gettime(&t0); for (int64_t j = 1; j < iterations; j++) { hdr_record_value(histogram, j); } hdr_gettime(&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 bool disk_scan_part(disk_t *disk, uint64_t offset, void *data, int data_size, struct scan_state *state) { ssize_t ret; struct timespec t_start; struct timespec t_end; uint64_t t; int error = 0; io_result_t io_res; clock_gettime(CLOCK_MONOTONIC, &t_start); ret = disk_dev_read(&disk->dev, offset, data_size, data, &io_res); clock_gettime(CLOCK_MONOTONIC, &t_end); t = (t_end.tv_sec - t_start.tv_sec) * 1000000000 + t_end.tv_nsec - t_start.tv_nsec; const uint64_t t_msec = t / 1000000; // Perform logging data_log_raw(&disk->data_raw, offset/disk->sector_size, data_size/disk->sector_size, &io_res, t); data_log(&disk->data_log, offset/disk->sector_size, data_size/disk->sector_size, &io_res, t); // Handle error or incomplete data if (io_res.data != DATA_FULL || io_res.error != ERROR_NONE) { int s_errno = errno; ERROR("Error when reading at offset %" PRIu64 " size %d read %zd, errno=%d: %s", offset, data_size, ret, errno, strerror(errno)); ERROR("Details: error=%s data=%s %02X/%02X/%02X", error_to_str(io_res.error), data_to_str(io_res.data), io_res.info.sense_key, io_res.info.asc, io_res.info.ascq); report_scan_error(disk, offset, data_size, t); disk->num_errors++; error = 1; if (io_res.error == ERROR_FATAL) { ERROR("Fatal error occurred, bailing out."); return false; } if (io_res.error == ERROR_UNKNOWN) { if (state->num_unknown_errors++ > 500) { ERROR("%u unknown errors occurred, assuming fatal issue.", state->num_unknown_errors); return false; } ERROR("Unknown error occurred, possibly untranslated error by storage layers, trying to continue."); } if (s_errno != EIO && s_errno != 0) abort(); // TODO: What to do when no everything was read but errno is zero? } else { state->num_unknown_errors = 0; // Clear non-consecutive unknown errors report_scan_success(disk, offset, data_size, t); } hdr_record_value(disk->histogram, t / 1000); latency_bucket_add(disk, t_msec, state); if (t_msec > 1000) { VERBOSE("Scanning at offset %" PRIu64 " took %"PRIu64" msec", offset, t_msec); } if (disk->fix && (t_msec > 3000 || error)) { if (io_res.error != ERROR_UNCORRECTED) { INFO("Fixing region by rewriting, offset=%"PRIu64" size=%d", offset, data_size); ret = disk_dev_write(&disk->dev, offset, data_size, data, &io_res); if (ret != data_size) { ERROR("Error while attempting to rewrite the data! ret=%zd errno=%d: %s", ret, errno, strerror(errno)); } } else { // When we correct uncorrectable errors we want to zero it out, this should reduce any confusion later on when the data is read unsigned fix_offset = 0; int fix_size = 4096; if (data_size < fix_size) fix_size = data_size; for (; data_size >= (int)(fix_offset + fix_size); fix_offset += fix_size) { disk_dev_read(&disk->dev, offset+fix_offset, fix_size, data, &io_res); if (io_res.error == ERROR_UNCORRECTED) { INFO("Fixing uncorrectable region by writing zeros, offset=%"PRIu64" size=%d", offset+fix_offset, fix_size); memset(data, 0, fix_size); ret = disk_dev_write(&disk->dev, offset+fix_offset, fix_size, data, &io_res); if (ret != data_size) { ERROR("Error while attempting to overwrite uncorrectable data! ret=%zd errno=%d: %s", ret, errno, strerror(errno)); } } } } } return true; }
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); }
void record_value(int64_t value) { int64_t critical_value_enter = phaser_.writer_critical_section_enter(); hdr_histogram* h = histograms_[active_index_.load()]; hdr_record_value(h, value); phaser_.writer_critical_section_end(critical_value_enter); }
void record_value(int64_t value) { hdr_record_value(histogram_, value); }