python-peps/pep-0418/bench_time.c

163 lines
3.7 KiB
C
Raw Normal View History

2012-04-11 18:32:44 -04:00
/*
* Benchmark program written for the PEP 418.
*
* gcc bench_time.c -O3 -lrt -o bench_time && ./bench_time
*/
#include <time.h>
#include <stdio.h>
#include <sys/time.h>
#define NRUN 5
#define NLOOP 1000000
#define UNROLL(expr) \
expr; expr; expr; expr; expr; expr; expr; expr; expr; expr
#define NUNROLL 10
typedef struct {
const char *name;
clockid_t identifier;
} CLOCK;
CLOCK clocks[] = {
#ifdef CLOCK_REALTIME_COARSE
{"CLOCK_REALTIME_COARSE", CLOCK_REALTIME_COARSE},
#endif
#ifdef CLOCK_MONOTONIC_COARSE
{"CLOCK_MONOTONIC_COARSE", CLOCK_MONOTONIC_COARSE},
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
{"CLOCK_THREAD_CPUTIME_ID", CLOCK_THREAD_CPUTIME_ID},
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
{"CLOCK_PROCESS_CPUTIME_ID", CLOCK_PROCESS_CPUTIME_ID},
#endif
#ifdef CLOCK_MONOTONIC_RAW
{"CLOCK_MONOTONIC_RAW", CLOCK_MONOTONIC_RAW},
#endif
#ifdef CLOCK_VIRTUAL
{"CLOCK_VIRTUAL", CLOCK_VIRTUAL},
#endif
#ifdef CLOCK_UPTIME_FAST
{"CLOCK_UPTIME_FAST", CLOCK_UPTIME_FAST},
#endif
#ifdef CLOCK_UPTIME_PRECISE
{"CLOCK_UPTIME_PRECISE", CLOCK_UPTIME_PRECISE},
#endif
#ifdef CLOCK_UPTIME
{"CLOCK_UPTIME", CLOCK_UPTIME},
#endif
#ifdef CLOCK_MONOTONIC_FAST
{"CLOCK_MONOTONIC_FAST", CLOCK_MONOTONIC_FAST},
#endif
#ifdef CLOCK_MONOTONIC_PRECISE
{"CLOCK_MONOTONIC_PRECISE", CLOCK_MONOTONIC_PRECISE},
#endif
#ifdef CLOCK_REALTIME_FAST
{"CLOCK_REALTIME_FAST", CLOCK_REALTIME_FAST},
#endif
#ifdef CLOCK_REALTIME_PRECISE
{"CLOCK_REALTIME_PRECISE", CLOCK_REALTIME_PRECISE},
#endif
#ifdef CLOCK_SECOND
{"CLOCK_SECOND", CLOCK_SECOND},
#endif
#ifdef CLOCK_PROF
{"CLOCK_PROF", CLOCK_PROF},
#endif
{"CLOCK_MONOTONIC", CLOCK_MONOTONIC},
{"CLOCK_REALTIME", CLOCK_REALTIME}
};
#define NCLOCKS (sizeof(clocks) / sizeof(clocks[0]))
void bench_clock_gettime(clockid_t clkid)
{
unsigned long loop;
struct timespec tmpspec;
for (loop=0; loop<NLOOP; loop++) {
UNROLL( (void)clock_gettime(clkid, &tmpspec) );
}
}
void bench_time(clockid_t clkid)
{
unsigned long loop;
for (loop=0; loop<NLOOP; loop++) {
UNROLL( (void)time(NULL) );
}
}
void bench_usleep(clockid_t clkid)
{
unsigned long loop;
for (loop=0; loop<NLOOP; loop++) {
UNROLL( (void)usleep(1000) );
}
}
void bench_gettimeofday(clockid_t clkid)
{
unsigned long loop;
struct timeval tmpval;
for (loop=0; loop<NLOOP; loop++) {
UNROLL( (void)gettimeofday(&tmpval, NULL) );
}
}
void bench_clock(clockid_t clkid)
{
unsigned long loop;
for (loop=0; loop<NLOOP; loop++) {
UNROLL( (void)clock() );
}
}
void benchmark(const char *name, void (*func) (clockid_t clkid), clockid_t clkid)
{
unsigned int run;
double dt, best;
struct timespec before, after, tmpspec;
struct timeval tmpval;
best = 0;
for (run=0; run<NRUN; run++) {
clock_gettime(CLOCK_MONOTONIC, &before);
(*func) (clkid);
clock_gettime(CLOCK_MONOTONIC, &after);
dt = after.tv_sec - before.tv_sec;
if (after.tv_nsec >= before.tv_nsec)
dt += (after.tv_nsec - before.tv_nsec) * 1e-9;
else
{
dt -= 1.0;
dt += (before.tv_nsec - after.tv_nsec) * 1e-9;
}
dt *= (double)1e9 / NLOOP / NUNROLL;
if (best != 0.0) {
if (dt < best)
best = dt;
}
else
best = dt;
}
printf("%s: %.0f ns\n", name, best, NLOOP);
}
int main()
{
clockid_t clkid;
int i;
for (i=0; i<NCLOCKS; i++) {
benchmark(clocks[i].name, bench_clock_gettime, clocks[i].identifier);
}
benchmark("clock()", bench_clock, 0);
benchmark("gettimeofday()", bench_gettimeofday, 0);
benchmark("time()", bench_time, 0);
return 0;
}