From e20e275081d888abb45cbfbf1f68b5e2bffef052 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 16 Oct 2016 14:15:59 -0700 Subject: [PATCH] prog_util: use QueryPerformanceCounter() on Windows QueryPerformanceCounter() is much more accurate than GetSystemTimeAsFileTime(). Also avoid converting into a specific time unit until the results need to be displayed. This is more efficient and avoids losing precision. --- programs/benchmark.c | 16 +++++++-------- programs/checksum.c | 8 ++++---- programs/prog_util.c | 47 +++++++++++++++++++++++++++++++++++++------- programs/prog_util.h | 4 +++- 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/programs/benchmark.c b/programs/benchmark.c index 625e1c1..ad1aa99 100644 --- a/programs/benchmark.c +++ b/programs/benchmark.c @@ -352,26 +352,26 @@ do_benchmark(struct file_stream *in, void *original_buf, void *compressed_buf, total_uncompressed_size += original_size; /* Compress the chunk of data. */ - start_time = current_time(); + start_time = timer_ticks(); compressed_size = do_compress(compressor, original_buf, original_size, compressed_buf, original_size - 1); - total_compress_time += current_time() - start_time; + total_compress_time += timer_ticks() - start_time; if (compressed_size) { /* Successfully compressed the chunk of data. */ /* Decompress the data we just compressed and compare * the result with the original. */ - start_time = current_time(); + start_time = timer_ticks(); result = do_decompress(decompressor, compressed_buf, compressed_size, decompressed_buf, original_size); - total_decompress_time += current_time() - start_time; + total_decompress_time += timer_ticks() - start_time; if (!result) { msg("%"TS": failed to decompress data", @@ -414,11 +414,11 @@ do_benchmark(struct file_stream *in, void *original_buf, void *compressed_buf, (unsigned int)(total_compressed_size * 100000 / total_uncompressed_size % 1000)); printf("\tCompression time: %"PRIu64" ms (%"PRIu64" MB/s)\n", - total_compress_time / 1000000, - 1000 * total_uncompressed_size / total_compress_time); + timer_ticks_to_ms(total_compress_time), + timer_MB_per_s(total_uncompressed_size, total_compress_time)); printf("\tDecompression time: %"PRIu64" ms (%"PRIu64" MB/s)\n", - total_decompress_time / 1000000, - 1000 * total_uncompressed_size / total_decompress_time); + timer_ticks_to_ms(total_decompress_time), + timer_MB_per_s(total_uncompressed_size, total_decompress_time)); return 0; } diff --git a/programs/checksum.c b/programs/checksum.c index ea6c33c..eda4c16 100644 --- a/programs/checksum.c +++ b/programs/checksum.c @@ -79,9 +79,9 @@ checksum_stream(struct file_stream *in, cksum_fn_t cksum, u32 *sum, break; size += ret; - start_time = current_time(); + start_time = timer_ticks(); *sum = cksum(*sum, buf, ret); - elapsed += current_time() - start_time; + elapsed += timer_ticks() - start_time; } if (elapsed == 0) @@ -178,8 +178,8 @@ tmain(int argc, tchar *argv[]) if (do_timing) { printf("%08"PRIx32"\t%"TS"\t" "%"PRIu64" ms\t%"PRIu64" MB/s\n", - sum, in.name, elapsed / 1000000, - 1000 * size / elapsed); + sum, in.name, timer_ticks_to_ms(elapsed), + timer_MB_per_s(size, elapsed)); } else { printf("%08"PRIx32"\t%"TS"\t\n", sum, in.name); } diff --git a/programs/prog_util.c b/programs/prog_util.c index b7695d8..6a59abe 100644 --- a/programs/prog_util.c +++ b/programs/prog_util.c @@ -102,16 +102,16 @@ xmalloc(size_t size) } /* - * Retrieve the current time in nanoseconds since a start time which is fixed - * for the duration of program execution but is otherwise unspecified + * Return the number of timer ticks that have elapsed since some unspecified + * point fixed at the start of program execution */ u64 -current_time(void) +timer_ticks(void) { #ifdef _WIN32 - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - return 100 * (((u64)ft.dwHighDateTime << 32) | ft.dwLowDateTime); + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + return count.QuadPart; #elif defined(HAVE_CLOCK_GETTIME) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); @@ -119,10 +119,43 @@ current_time(void) #else struct timeval tv; gettimeofday(&tv, NULL); - return (1000000000 * (u64)tv.tv_sec) + (1000 * (u64)tv.tv_usec); + return (1000000 * (u64)tv.tv_sec) + tv.tv_usec; #endif } +/* + * Return the number of timer ticks per second + */ +static u64 +timer_frequency(void) +{ +#ifdef _WIN32 + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + return freq.QuadPart; +#elif defined(HAVE_CLOCK_GETTIME) + return 1000000000; +#else + return 1000000; +#endif +} + +/* + * Convert a number of elapsed timer ticks to milliseconds + */ +u64 timer_ticks_to_ms(u64 ticks) +{ + return ticks * 1000 / timer_frequency(); +} + +/* + * Convert a byte count and a number of elapsed timer ticks to MB/s + */ +u64 timer_MB_per_s(u64 bytes, u64 ticks) +{ + return bytes * timer_frequency() / ticks / 1000000; +} + /* * Retrieve a pointer to the filename component of the specified path. * diff --git a/programs/prog_util.h b/programs/prog_util.h index db2579c..2aa35a4 100644 --- a/programs/prog_util.h +++ b/programs/prog_util.h @@ -120,7 +120,9 @@ extern void _printf(1, 2) msg_errno(const char *fmt, ...); extern void *xmalloc(size_t size); -extern u64 current_time(void); +extern u64 timer_ticks(void); +extern u64 timer_ticks_to_ms(u64 ticks); +extern u64 timer_MB_per_s(u64 bytes, u64 ticks); extern const tchar *get_filename(const tchar *path);