Salut,
Je me suis tenté une implémentation avec setitimer...
#define _POSIX_C_SOURCE 199309L#include<stdio.h>// #include <sys/timerfd.h>#include<errno.h>#include<string.h>#include<stdlib.h>// #include <unistd.h>#include<sys/mman.h>//#include <time.h>#include<unistd.h>#include<threads.h>#include<signal.h>#include<sys/time.h>#define COUNT 10001#define PERIODE 1000000 //1ms (in ns)mtx_tmyLock;void(*old_handler)(int);// sighandler_t don't work !!! :-(voidalarm_callback(intsig){// Unlock du mutex pour continuer la boucle.(void)mtx_unlock(&myLock);if((old_handler=signal(SIGALRM,alarm_callback))==SIG_ERR){fprintf(stderr,"Error setting SIGALARM in alarm_callback\n");return;}}intmain(intargc,charconst*argv[]){if(mtx_init(&myLock,mtx_plain)==thrd_error){fprintf(stderr,"Error creating mutex\n");return-1;}// Lock one time to init locked. First loop must unlockif(mtx_lock(&myLock)==thrd_error){fprintf(stderr,"Error locking mutex first time\n");return-1;}if((old_handler=signal(SIGALRM,alarm_callback))==SIG_ERR){fprintf(stderr,"Error setting SIGALARM\n");return-1;}structitimervalsetTimer,oldTimer;setTimer.it_interval.tv_sec=0;// Warning, c’est des us.setTimer.it_interval.tv_usec=PERIODE/1000;// First period start in 1ssetTimer.it_value.tv_sec=1;setTimer.it_value.tv_usec=0;// Timer values are defined by the following structures://// struct itimerval {// struct timeval it_interval; /* Interval for periodic timer */// struct timeval it_value; /* Time until next expiration */// };//// struct timeval {// time_t tv_sec; /* seconds */// suseconds_t tv_usec; /* microseconds */// };if(setitimer(ITIMER_REAL,&setTimer,&oldTimer)==-1){fprintf(stderr,"Setitimer initialization failed\n");return-1;}structtimespecnow,previous;longsomme=0;longpeak=PERIODE,base=PERIODE;longtabTimer[COUNT];__uint64_tret;if(clock_gettime(CLOCK_MONOTONIC,&previous)<0){printf("error clock_gettime : %s\n",strerror(errno));return-1;}for(size_ti=0;i<COUNT;i++){// Wait for syncif(mtx_lock(&myLock)==thrd_error){fprintf(stderr,"Error lock in loop number %d\n",i);return-1;}clock_gettime(CLOCK_MONOTONIC,&now);tabTimer[i]=(now.tv_sec-previous.tv_sec)*1000000000+now.tv_nsec-previous.tv_nsec;previous=now;}constlonghigh_10=PERIODE+PERIODE/10;constlonglow_10=PERIODE-PERIODE/10;inthigher=0;intlower=0;intnormal=0;//we write resultsfor(size_ti=1;i<COUNT;i++){// printf("[%2d] = %ld\n",i,tabTimer[i]);somme+=tabTimer[i];if(tabTimer[i]>peak){peak=tabTimer[i];}if(tabTimer[i]<base){base=tabTimer[i];}if(tabTimer[i]>high_10){higher++;}elseif(tabTimer[i]<low_10){lower++;}else{normal++;}}inttotal=lower+higher+normal;printf("average en ns = %ld, peak = %ld(+%2.2f%%), base = %ld(-%2.2f%%)\n",somme/(COUNT-1),peak,(((float)peak/PERIODE)-1)*100,base,(1.-((float)base)/PERIODE)*100);printf(" Total : %d,\n""\t- lower : %6d (%2.2f%%)\n""\t- normal: %6d (%2.2f%%)\n""\t- higher: %6d (%2.2f%%)\n",total,lower,100.*((float)lower)/total,normal,100.*((float)normal)/total,higher,100.*((float)higher)/total);return0;}
Pour le sigalarm, il faut le recabler à chaque fois.
Voici quelques stats, j’y ai ajouté le nombre de fois ou on a un écart de plus de 10%. De plus, si on déborde sur un cycle, la différence entre les deux sera forcément très inférieur sur le cycle suivant. D’où la relative symétrie (+ou- 1) entre les higher et les lower.
$ ./a.out
average en ns=999998, peak=1057467(+5.75%), base=944193(-5.58%)
Total : 10000,
- lower : 0(0.00%)
- normal: 10000(100.00%)
- higher: 0(0.00%)
$ ./a.out
average en ns=1000098, peak=2083044(+108.30%), base=603560(-39.64%)
Total : 10000,
- lower : 1(0.01%)
- normal: 9997(99.97%)
- higher: 2(0.02%)
$ ./a.out
average en ns=999998, peak=1206658(+20.67%), base=796835(-20.32%)
Total : 10000,
- lower : 2(0.02%)
- normal: 9997(99.97%)
- higher: 1(0.01%)
$ ./a.out
average en ns=999997, peak=1107952(+10.80%), base=894580(-10.54%)
Total : 10000,
- lower : 1(0.01%)
- normal: 9998(99.98%)
- higher: 1(0.01%)
$ su
Mot de passe :
##################### En Temps Réel####################
.../Linuxfr/TR# chrt 50 ./a.out
average en ns=999997, peak=1009857(+0.99%), base=978338(-2.17%)
Total : 10000,
- lower : 0(0.00%)
- normal: 10000(100.00%)
- higher: 0(0.00%)
.../Linuxfr/TR# chrt 50 ./a.out
average en ns=999997, peak=1011019(+1.10%), base=979650(-2.03%)
Total : 10000,
- lower : 0(0.00%)
- normal: 10000(100.00%)
- higher: 0(0.00%)
.../Linuxfr/TR# chrt 50 ./a.out
average en ns=999997, peak=1009547(+0.95%), base=976955(-2.30%)
Total : 10000,
- lower : 0(0.00%)
- normal: 10000(100.00%)
- higher: 0(0.00%)
.../Linuxfr/TR# chrt 50 ./a.out
average en ns=999997, peak=1015868(+1.59%), base=979951(-2.00%)
Total : 10000,
- lower : 0(0.00%)
- normal: 10000(100.00%)
- higher: 0(0.00%)
.../SSD/C++/Linuxfr/TR#
Un essai supplémentaire sur 2 minutes (2 ×ばつかける 60 ×ばつかける 1000 =わ 120 000ms)
$ ./a.out
average en ns=999999, peak=1425844(+42.58%), base=585376(-41.46%)
Total : 120000,
- lower : 22(0.02%)
- normal: 119955(99.96%)
- higher: 23(0.02%)
$ su
Mot de passe :
.../Linuxfr/TR# chrt 50 ./a.out
average en ns=999999, peak=1030337(+3.03%), base=968720(-3.13%)
Total : 120000,
- lower : 0(0.00%)
- normal: 120000(100.00%)
- higher: 0(0.00%)# Ajout d'une affinité CPU
.../Linuxfr/TR# taskset 1 chrt 50 ./a.out
average en ns=999999, peak=1272574(+27.26%), base=727705(-27.23%)
Total : 120000,
- lower : 10(0.01%)
- normal: 119981(99.98%)
- higher: 9(0.01%)
.../C++/Linuxfr/TR#
En forçant l’affinité sur un CPU, on augmente l’erreur... ça ma surpris. Il faudrait voir si on peut interdire un CPU à tout le monde sauf un processus ;-)
Après, j'avais choisi le CPU 0, peut-être que en prenant le 3...
Linuxfr/TR# taskset 4 chrt 50 ./a.out
average en ns=999999, peak=1018414(+1.84%), base=971595(-2.84%)
Total : 120000,
- lower : 0(0.00%)
- normal: 120000(100.00%)
- higher: 0(0.00%)
.../Linuxfr/TR#
C’est mieux... est-ce le hazard, ou les IT sont cablé sur le premier CPU sous Linux ?
# setitimer
Posté par Anthony Jaguenaud . En réponse au message probleme pour faire un timer précis de l'ordre de la milliseconde. Évalué à 6.
Salut,
Je me suis tenté une implémentation avec setitimer...
Pour le sigalarm, il faut le recabler à chaque fois.
Voici quelques stats, j’y ai ajouté le nombre de fois ou on a un écart de plus de 10%. De plus, si on déborde sur un cycle, la différence entre les deux sera forcément très inférieur sur le cycle suivant. D’où la relative symétrie (+ou- 1) entre les higher et les lower.
Un essai supplémentaire sur 2 minutes (2 ×ばつかける 60 ×ばつかける 1000 =わ 120 000ms)
En forçant l’affinité sur un CPU, on augmente l’erreur... ça ma surpris. Il faudrait voir si on peut interdire un CPU à tout le monde sauf un processus ;-)
Après, j'avais choisi le CPU 0, peut-être que en prenant le 3...
C’est mieux... est-ce le hazard, ou les IT sont cablé sur le premier CPU sous Linux ?
Voilà pour mes tests du soir.
Bonne nuit