1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| #include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
// Linux : link with librt : gcc -O3 -Wall main.c -lrt
// add a random arg to set SCHED_FIFO priority
/*
TEST with :
Env:
Linux sli-linux 2.6.13CIO-SLI-15-default #5 Thu Apr 5 11:29:06 CEST 2007 i686 i686 i386 GNU/Linux
Processor :
vendor_id : GenuineIntel
cpu family : 15
model : 2
model name : Intel(R) Pentium(R) 4 CPU 2.00GHz
stepping : 4
cpu MHz : 1994.327
cache size : 512 KB
gcc version 4.0.2 20050901 (prerelease) (SUSE Linux)
RESULTS :
sli@sli-linux:~/developpement/my_tests/test_clock_gettime> ./a.out
No sheduling change
resolution : 0 s 999848 nsec
classic scheduling, nanosleep(0 s, 999848 nsec), clock_gettime interval : 0 s 1408000 nsec
classic scheduling, nanosleep(0 s, 999848 nsec), gettimeofday interval : 0 s 1406 usec
relative accuracy of gettimeofday() to clockgettime() : -0.142248 %
classic scheduling, nanosleep(0 s, 499924 nsec), clock_gettime interval : 0 s 1515000 nsec
classic scheduling, nanosleep(0 s, 499924 nsec), gettimeofday interval : 0 s 1515 usec
relative accuracy of gettimeofday() to clockgettime() : 0.000000 %
sli@sli-linux:~/developpement/my_tests/test_clock_gettime> sudo ./a.out r
Password:
setting scheduling to FIFO
resolution : 0 s 999848 nsec
classic scheduling, nanosleep(0 s, 999848 nsec), clock_gettime interval : 0 s 1168000 nsec
classic scheduling, nanosleep(0 s, 999848 nsec), gettimeofday interval : 0 s 1166 usec
relative accuracy of gettimeofday() to clockgettime() : -0.171527 %
classic scheduling, nanosleep(0 s, 499924 nsec), clock_gettime interval : 0 s 1939000 nsec
classic scheduling, nanosleep(0 s, 499924 nsec), gettimeofday interval : 0 s 1939 usec
relative accuracy of gettimeofday() to clockgettime() : 0.000000 %
CONCLUSION :
Whatever scheduling is sleep() resolution time is system resolution time (here 1ms)
The difference beetwenn clock_gettime() and gettimeofday() is negligible
However clock_gettime() is compatible SUSv2, POSIX 1003.1-2001 (manpages), when gettimeofday() not ( SVr4, BSD 4.3), and for portability reason it is always better to use POSIX functions. For linux you will have to check the librt availability.
TODO :
Make two list of measures and compare mediums
Check that with sched FIFO and <2ms tempo nanosleep() is more accurate.
*/
int main (int argc, char * argv[])
{
clockid_t clk_id = CLOCK_REALTIME ;
// resolution
struct timespec res, tp_start, tp_end ;
struct timeval tv_start, tv_end ;
// nanosleep
struct timespec req, rem, tick_adj ;
// shed
struct sched_param param ;
int i ;
float accuracy ;
// Set RT priority ?
if (argc > 1)
{
printf("setting scheduling to FIFO\n") ;
if (sched_getparam(0, ¶m ) == -1)
{
printf("error shed_get : %s\n", strerror(errno)) ;
return -1 ;
}
// manpage says priority must be >0 for fifo sched
param.sched_priority = 1 ;
if ( sched_setscheduler(0, SCHED_FIFO, ¶m) == -1)
{
printf("error shed_set : %s\n", strerror(errno)) ;
return -1 ;
}
}
else
{
printf("No sheduling change\n") ;
}
if ( clock_getres(clk_id, &res) == 0)
{
printf("resolution : %ld s %ld nsec\n", res.tv_sec, res.tv_nsec) ;
}
else
{
printf("err getting resolution : %s\n", strerror(errno));
return -1 ;
}
for (i = 1 ; i < 3 ; i++)
{
// manpage says : nanosleep sleep at least a time slice (i386=10ms), unless SCHED_FIFO/SCHED_RR for process (in this case 1us)
// Now sleep a 'RT' time resolution / i to check nanosleep resolution in the Linux Classic Scheduling
req = res ;
req.tv_sec /= i ;
req.tv_nsec /= i ;
// put a non-active sleep here to start on a tick.
tick_adj.tv_sec = 0 ;
tick_adj.tv_nsec = 20 * 1000000 ;
nanosleep(&tick_adj, NULL) ;
// We 'hope' that execution of clock_gettime+gettimeofday+nanosleep < tick duration
clock_gettime(clk_id,&tp_start) ;
gettimeofday(&tv_start, NULL) ;
if(nanosleep(&req, &rem) == 0)
{
clock_gettime(clk_id,&tp_end) ;
gettimeofday(&tv_end, NULL) ;
printf("classic scheduling, nanosleep(%ld s, %ld nsec), clock_gettime interval : %ld s %ld nsec\n",
res.tv_sec / i, res.tv_nsec / i ,
tp_end.tv_sec - tp_start.tv_sec, tp_end.tv_nsec - tp_start.tv_nsec) ;
printf("classic scheduling, nanosleep(%ld s, %ld nsec), gettimeofday interval : %ld s %ld usec\n",
res.tv_sec /i , res.tv_nsec /i ,
tv_end.tv_sec - tv_start.tv_sec, tv_end.tv_usec - tv_start.tv_usec) ;
// printf relative accuracy (rounded to us) :
accuracy = 1.0 - (float)((tp_end.tv_sec - tp_start.tv_sec)*1000000 + (tp_end.tv_nsec - tp_start.tv_nsec)/1000) / (float)( (tv_end.tv_sec - tv_start.tv_sec)*1000000 + tv_end.tv_usec - tv_start.tv_usec) ;
accuracy *= 100.0 ;
printf("relative accuracy of gettimeofday() to clockgettime() : %f %% \n", accuracy) ;
}
else
{
printf("interrupted sleep, aborting : %s\n", strerror(errno)) ;
}
}
return 0 ;
} |
Partager