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.
This commit is contained in:
Eric Biggers 2016-10-16 14:15:59 -07:00
parent 7662390f55
commit e20e275081
4 changed files with 55 additions and 20 deletions

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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.
*

View File

@ -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);