[Developers] Proposed Cactus Timer API (Posix timers)

Steve White swhite at aei.mpg.de
Wed Aug 11 16:46:26 CDT 2004


Since we're on the topic, I thought I'd try out some other timers that
are laying around.  The POSIX timers ('clock_gettime' etc) are high
resolution (in principle down to nanoseconds) and have a means of 
reporting resolution ('clock_getres').

Attached find a program that sees how long each clock takes to turn
over and prints the reported resolution of each.
	gcc -c clock.c
	gcc clock.o -lrt
	./a.out

The POSIX clocks also have something resembling the Cactus timer's
modularity: clocks can be added that use the same interface.

Drawbacks:  Not quite as universal as gettimeofday, getrusage. Some clocks
are missing on some systems (Peyote and the Xeons are missing the
MONOTONIC clock).

Bugs:  It would appear that the resolution function is just wrong for some
clocks, reporting a resolution much larger than the time required for the
clock to turn over.

Here's the Peyote output:
	CLOCK_PROCESS_CPUTIME_ID
	3.002000e-06 sec turnover; 1 iterations
	resolution 1.000000e-09 sec

	CLOCK_REALTIME
	1.000000e-06 sec turnover; 1 iterations
	CLOCK_REALTIME resolution 1.000000e-02 sec

	no CLOCK_MONOTONIC

	CLOCK_THREAD_CPUTIME_ID
	1.939000e-06 sec turnover; 1 iterations
	resolution 1.000000e-09 sec

Note the PROCESS and THREAD_CPUTIME clocks report 1 nanosecond resolution,
which isn't wrong, in the non-strict sense of a lower bound (it could be
considered overly optimistic).  But the REALTIME clock reports a
resolution that is much larger than the smallest turnover time.  I think
this renders the resolution function questionable, if not useless.

------------------------------------------------------------------------
Steve White : Programmer
Max-Planck-Institut für Gravitationsphysik      Albert-Einstein-Institut
Am Mühlenberg 1, D-14476 Golm, Germany                  +49-331-567-7329

-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

/* on my Linux, this is contained in librt.a */

/* SUSv2, POSIX 1003.1-2001 */    

#if !defined _POSIX_TIMERS ||  _POSIX_TIMERS <= 0
	#error "Requires POSIX timers (clock_gettime etc.)" 
#else
double 
timespec_diffsecs( const struct timespec *begin, const struct timespec *end )
{
	if( end->tv_nsec < begin->tv_nsec )	/* borrow */
		return ( 1.0 - begin->tv_nsec + end->tv_nsec ) * 1.e-9
		+ ( end->tv_sec - 1 - begin->tv_sec );
	else
		return ( end->tv_nsec - begin->tv_nsec ) * 1.e-9
		+ ( end->tv_sec - begin->tv_sec );
}

double 
timespec_secs( const struct timespec *ts )
{
	return ts->tv_nsec * 1.e-9 + ts->tv_sec;
}

int
main()
{
	int i;
	int bla, how;
	struct timespec begin, end;
	struct timespec tp;

#ifdef _POSIX_CPUTIME
	printf( "CLOCK_PROCESS_CPUTIME_ID\n" );
	bla = clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &begin );

	for( i = 1; i < 100000; i++ )
	{
		bla = clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &end );
		if( end.tv_nsec > begin.tv_nsec )
		{
			printf( "%e sec turnover; %d iterations\n",
				timespec_diffsecs( &begin, &end ), i );
			break;
		}
	}
	how = clock_getres( CLOCK_PROCESS_CPUTIME_ID, &tp );
	printf( "resolution %e sec\n\n", timespec_secs( &tp ) );
#else
	printf( "no CLOCK_PROCESS_CPUTIME_ID \n\n" );
#endif

	printf( "CLOCK_REALTIME\n" );
	bla = clock_gettime( CLOCK_REALTIME, &begin );

	for( i = 1; i < 100000; i++ )
	{
		double s = 0.0;
		bla = clock_gettime( CLOCK_REALTIME, &end );
		if( end.tv_sec != begin.tv_sec
		||  end.tv_nsec != begin.tv_nsec )
		{
			printf( "%e sec turnover; %d iterations\n", 
				timespec_diffsecs( &begin, &end ), i );
			break;
		}
	}
	how = clock_getres( CLOCK_REALTIME, &tp );
	printf( "CLOCK_REALTIME resolution %e sec\n\n", timespec_secs( &tp ) );

#ifdef _POSIX_MONOTONIC_CLOCK
	printf( "CLOCK_MONOTONIC\n" );
	bla = clock_gettime( CLOCK_MONOTONIC, &begin );

	for( i = 1; i < 100000; i++ )
	{
		bla = clock_gettime( CLOCK_MONOTONIC, &end );
		if( end.tv_nsec > begin.tv_nsec )
		{
			printf( "%e sec turnover; %d iterations\n", 
				timespec_diffsecs( &begin, &end ), i );
			break;
		}
	}
	how = clock_getres( CLOCK_MONOTONIC, &tp );
	printf( "CLOCK_MONOTONIC resolution %e sec\n\n", timespec_secs( &tp ) );
#else
	printf( "no CLOCK_MONOTONIC \n\n" );
#endif

#ifdef _POSIX_THREAD_CPUTIME
	printf( "CLOCK_THREAD_CPUTIME_ID\n" );

	bla = clock_gettime( CLOCK_THREAD_CPUTIME_ID, &begin );

	for( i = 1; i < 100000; i++ )
	{
		bla = clock_gettime( CLOCK_THREAD_CPUTIME_ID, &end );
		if( end.tv_nsec > begin.tv_nsec )
		{
			printf( "%e sec turnover; %d iterations\n", 
				timespec_diffsecs( &begin, &end ), i );
			break;
		}
	}
	how = clock_getres( CLOCK_THREAD_CPUTIME_ID, &tp );
	printf( "resolution %e sec\n", timespec_secs( &tp ) );
#else
	printf( "no CLOCK_THREAD_CPUTIME_ID \n\n" );
#endif

	return 0;
}

#endif


More information about the Developers mailing list