Skip to content

Instantly share code, notes, and snippets.

@nickolayl
Created May 25, 2020 11:26
Show Gist options
  • Save nickolayl/f6651e978db145141faa1d986182014f to your computer and use it in GitHub Desktop.
Save nickolayl/f6651e978db145141faa1d986182014f to your computer and use it in GitHub Desktop.
Cross-platform, drop-in, high resolution timer for C/C++ projects.
/* ----------------------------------------------------------------------- */
/*
Easy embeddable cross-platform high resolution timer function. For each
platform we select the high resolution timer. You can call the 'ns()'
function in your file after embedding this.
*/
#include <stdint.h>
#if defined(__linux)
# define HAVE_POSIX_TIMER
# include <time.h>
# ifdef CLOCK_MONOTONIC
# define CLOCKID CLOCK_MONOTONIC
# else
# define CLOCKID CLOCK_REALTIME
# endif
#elif defined(__APPLE__)
# define HAVE_MACH_TIMER
# include <mach/mach_time.h>
#elif defined(_WIN32)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif
static uint64_t ns() {
static uint64_t is_init = 0;
#if defined(__APPLE__)
static mach_timebase_info_data_t info;
if (0 == is_init) {
mach_timebase_info(&info);
is_init = 1;
}
uint64_t now;
now = mach_absolute_time();
now *= info.numer;
now /= info.denom;
return now;
#elif defined(__linux)
static struct timespec linux_rate;
if (0 == is_init) {
clock_getres(CLOCKID, &linux_rate);
is_init = 1;
}
uint64_t now;
struct timespec spec;
clock_gettime(CLOCKID, &spec);
now = spec.tv_sec * 1.0e9 + spec.tv_nsec;
return now;
#elif defined(_WIN32)
static LARGE_INTEGER win_frequency;
if (0 == is_init) {
QueryPerformanceFrequency(&win_frequency);
is_init = 1;
}
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (uint64_t) ((1e9 * now.QuadPart) / win_frequency.QuadPart);
#endif
}
/* ----------------------------------------------------------------------- */
@SollyBunny
Copy link

SollyBunny commented Jun 29, 2024

This is great, but has a few problems

  1. Doesn't support posix like non linux systems, I've just made it default to posix / linux
  2. Weird indentation
  3. Doens't work in stricter C contexts (posix source undefined, mixed code and declerations, empty function args)

Here's my version:

/*
	Easy embeddable cross-platform high resolution timer function. For each 
	platform we select the high resolution timer. You can call the 'ns()' 
	function in your file after embedding this.
	https://gist.github.com/nickolayl/f6651e978db145141faa1d986182014f
*/
#include <stdint.h>
#if defined(__APPLE__)
	#include <mach/mach_time.h>
#elif defined(_WIN32)
	#include <windows.h>
#else
	#ifdef _POSIX_C_SOURCE
		#define NS_OLD_POSIX_C_SOURCE _POSIX_C_SOURCE
		#undef _POSIX_C_SOURCE
	#endif
	#define _POSIX_C_SOURCE 199309L
	#ifndef __USE_POSIX199309
		#define __USE_POSIX199309
		#define NS_DEFINED__USE_POSIX199309
	#endif
	#include <time.h>
	#ifdef NS_DEFINED__USE_POSIX199309
		#undef __USE_POSIX199309
	#endif
	#ifdef NS_OLD_POSIX_C_SOURCE
		#undef _POSIX_C_SOURCE
		#define _POSIX_C_SOURCE NS_OLD_POSIX_C_SOURCE
	#endif
	#ifdef CLOCK_MONOTONIC
		#define NS_CLOCK_ID CLOCK_MONOTONIC
	#else
		#define NS_CLOCK_ID CLOCK_REALTIME
	#endif
#endif
static inline uint64_t ns(void) {
	static uint8_t ns_inited = 0;
	#if defined(__APPLE__)
		static mach_timebase_info_data_t info;
		uint64_t now;
		if (ns_inited == 0) {
			mach_timebase_info(&info);
			ns_inited = 1;
		}
		now = mach_absolute_time();
		now *= info.numer;
		now /= info.denom;
		return now;
	#elif defined(_WIN32)
		static LARGE_INTEGER win_frequency;
		LARGE_INTEGER now;
		if (ns_inited == 0) {
			QueryPerformanceFrequency(&win_frequency);
			ns_inited = 1;
		}
		QueryPerformanceCounter(&now);
		return (uint64_t)((1.0e9 * now.QuadPart) / win_frequency.QuadPart);
	#else
		static struct timespec linux_rate;
		uint64_t now;
		struct timespec spec;
		if (ns_inited == 0) {
			clock_getres(NS_CLOCK_ID, &linux_rate);
			ns_inited = 1;
		}
		clock_gettime(NS_CLOCK_ID, &spec);
		now = spec.tv_sec * (uint64_t)1.0e9 + spec.tv_nsec;
		return now;
	#endif
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment