vă mulțumesc pentru comentariile dvs.! Aș dori să actualizez timpul curentă pentru a vă conecta ca ngx_time_update(). Mi-am schimbat exemplul meu pentru a utiliza doar CLOCK_REALTIME, dar întotdeauna aproximativ 400 microsecunde târziu. Github.com/hnakamur/iorn/commit / … Asta înseamnă că acest clock_gettime durează aproximativ 400 de nanosecunde pe mașina mea?

da, sună doar, într-un fel. Dar, dacă vă aflați pe un PC x86 PC-ul pe Linux, 400 ns pentru clock_gettime Overheads poate fi un pic mai mare (ordinea de magnitudine superioară – Vezi mai jos). Dacă utilizați un procesor arm (de exemplu, Raspberry Pi, nvidia jetson), acest lucru poate fi corect.

Nu știu cum primești 400 de microsecunde. Dar, a trebuit să fac multe lucruri în timp real pe Linux, iar 400 este similar cu ceea ce am măsurat ca o supraîncărcare pentru a face o schimbare de context și / sau de a trezi un proces / fir după o syscall suspendare.

i folosesc gettimeofday mai mult. Acum folosesc doar clock_gettime(CLOCK_REALTIME,...) pentru că este același, cu excepția faptului că obțineți nanosecunde în loc de microsecunde.

doar pentru tine să știi, deși clock_gettime este un apel de sistem, în zilele noastre, pe majoritatea sistemelor, utilizează stratul VDSO. Corele injectează codul special în aplicarea spațiului utilizator, astfel încât să poată accesa direct la timp fără supraîncărcarea unui . .

Dacă sunteți Interesați, puteți rula sub gdb și dezasamblați codul pentru a vedea că accesează pur și simplu anumite locații speciale de memorie în loc să efectueze un apel de sistem.

Nu cred că nu cred Aveți prea mult să vă faceți griji. Utilizați clock_gettime(CLOCK_MONOTONIC,...) și setați-l flags din 0. Iepheads nu sunt luate în considerare, în scopul ioring Apel, pentru că stratul iorn se utilizează.

Când fac acest lucru așa și că vreau / trebuie să Calculați costul suplimentar al clock_gettime IT clock_gettime Loop (de exemplu 1000 de ori) și încerc să păstrez timpul total sub o felie de timp. Folosesc diferența minimă între orele din fiecare iterație. Acest lucru compensează timp de tăiere.

Minimul este costul suplimentar al apelului în sine.

Există alte sfaturi pe care le puteți face pentru a minimiza latența în spațiul utilizatorului (de exemplu, Creșterea priorității procesului, blocați afinitatea procesorului și afinitatea de întrerupere a I / O), dar pot implica alte lucruri și, dacă nu sunteți foarte atenți, ele pot produce rezultate mai rele.

înainte de a începe să luați luarea Acțiuni extraordinare, trebuie să aveți o metodologie solidă pentru programul de analiză de măsurare / comparativ pentru a dovedi că rezultatele dvs. nu pot răspunde cerințelor dvs. de calendar / debit / latență. În caz contrar, faceți lucruri complicate fără nici un avantaj / necesar / necesar.

mai jos, un cod pe care l-am creat, simplificat, dar pe baza codului pe care l-am folosit deja pentru calibrarea supraîncărcării:

#include <stdio.h>#include <time.h>#define ITERMAX 10000typedef long long tsc_t;// tscget -- get time in nanosecondsstatic inline tsc_ttscget(void){ struct timespec ts; tsc_t tsc; clock_gettime(CLOCK_MONOTONIC,&ts); tsc = ts.tv_sec; tsc *= 1000000000; tsc += ts.tv_nsec; return tsc;}// tscsec -- convert nanoseconds to fractional secondsdoubletscsec(tsc_t tsc){ double sec; sec = tsc; sec /= 1e9; return sec;}tsc_tcalibrate(void){ tsc_t tscbeg; tsc_t tscold; tsc_t tscnow; tsc_t tscdif; tsc_t tscmin; int iter; tscmin = 1LL << 62; tscbeg = tscget(); tscold = tscbeg; for (iter = ITERMAX; iter > 0; --iter) { tscnow = tscget(); tscdif = tscnow - tscold; if (tscdif < tscmin) tscmin = tscdif; tscold = tscnow; } tscdif = tscnow - tscbeg; printf("MIN:%.9f TOT:%.9f AVG:%.9f\n", tscsec(tscmin),tscsec(tscdif),tscsec(tscnow - tscbeg) / ITERMAX); return tscmin;}intmain(void){ calibrate(); return 0;}

pe sistemul meu, un miez i7 la 2,67 GHz, ieșirea este:

MIN:0.000000019 TOT:0.000254999 AVG:0.000000025

Deci, primesc 25 ns de cheltuieli generale. Dar, din nou, fiecare sistem poate fi diferit într-o oarecare măsură.

Update:

Rețineți că procesoarele x86 au o „viteză” . Sistemul de operare poate crește sau micșora frecvența semi-automat a procesorului. Vitezele mai mici economisesc energia. Vitezele mai mari sunt performanțe maxime.

Acest lucru se face cu o euristică (de exemplu, dacă sistemul de operare detectează că procesul este un utilizator mare al procesorului, va crește viteza)

Pentru a forța viteza maximă, Linux în acest director:

/sys/devices/system/cpu/cpuN/cpufreq

unde N este numărul de CPU (de exemplu 0-7)

În acest director, există o serie de fișiere de interes. Acestea ar trebui să fie explicite.

În special, uitați-vă la scaling_governor. Are ondemand sau performance.

Pentru a forța viteza maximă, ca root, setați acest lucru pe performance (de exemplu):

echo "performance" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

Faceți acest lucru pentru toate procesoarele.

Cu toate acestea, am făcut-o pe sistemul meu și am avut un efect redus. Astfel, kernelul euristic se poate îmbunătăți.

În ceea ce privește 400 de ani, când un proces se așteaptă la ceva, când este „treaz”, este un proces în două etape.

Procesul este marcat „executabil”.

La un moment dat, sistemul / procesorul efectuează o replanificare. Procesul va fi executat în conformitate cu politica de planificare și prioritate din proces.

Pentru multe apeluri de sistem, replanificarea are loc în timpul următorului cronometru / ceas / întrerupere a sistemului. Astfel, pentru unii, poate exista o întârziere care poate merge până la un ceas complet (adică) pentru o valoare de 1000, acest lucru poate merge până la 1 ms (1000 US) mai târziu.

În medie, aceasta reprezintă jumătate sau 500.

pentru unele apeluri de sistem, atunci când procesul este marcat ca executabil, o replanificare este efectuată imediat. Dacă procesul are o prioritate mai mare, acesta va fi executat imediat.

Când m-am uitat la aceasta pentru prima dată, am urmărit toate căile de cod din kernel și singurul apel de sistem care a făcut imediat Replanning a fost SYSV IPC, pentru msgsnd/msgrcv. Cu alte cuvinte, atunci când procesul a făcut msgsnd, orice proces B așteaptă mesajul mesajului dat fiind executat.

dar alții nu (de exemplu futex). Ei ar aștepta temporizatorul. Multe lucruri s-au schimbat de atunci, iar acum, mai multe sysmalls vor face o amânare imediată. De exemplu, am măsurat recent futex și părea să facă replanning rapid.

Mai mult decât atât, planificatorul kernel sa schimbat. Noul programator poate trezi / efectua anumite lucruri pe o fracțiune de ceas. Deci, pentru tine, 400, este alinierea la următorul ceas.

Dar, ar putea fi pur și simplu supraîncărcarea pentru a face apelul sistemului. Pentru a testa acest lucru, mi-am schimbat programul de testare pentru a deschide /dev/null și a adăugat read(fd,buf,1) la bucla de testare.

Am primit o valoare MIN: de 529 US. Astfel, întârzierea pe care o obțineți ar putea fi pur și simplu timpul necesar pentru a face schimbarea postului.

Asta aș numi „destul de bine pentru moment”.

pentru a obține răspunsul „Razor „, probabil că va trebui să scrieți un șofer de bază personalizat și să faceți acest lucru. Aceasta este ceea ce ar face sistemele încorporate dacă se datorează (de exemplu) să comute un PIN GPIO PIN la fiecare interval.

dar, dacă tot ce faci este , supraîncărcare și subiacentul au write(1,...) tendința de a scufunda întârzierea reală.

Rețineți, de asemenea, că atunci când faceți , creează tamponul de ieșire și când tamponul FILE *stdout este plin, Este golit prin write.

Pentru o performanță mai bună, este mai bine să faceți int len = sprintf(buf,"current time is ..."); write(1,buf,len); în plus, atunci când tu Faceți acest lucru, dacă sunt umplute tampoanele de kernel pentru I / O Tty, procesul va fi suspendat până când I / O a fost trimis la dispozitivul TTY.

Pentru a face acest lucru, trebuie să monitorizați spațiul disponibil și ignorați câteva mesaje dacă nu există suficient spațiu pentru a le conține.

Trebuie să faceți : ioctl(1,TIOCOUTQ,...) Pentru a obține spațiul disponibil și ignorați unele mesaje dacă este mai mică decât dimensiunea mesajului pe care doriți să o generați (de exemplu, len Valoare de mai sus).

Pentru utilizarea dvs., probabil că sunteți mai interesat în ultimul mesaj, mai degrabă decât să ieșiți la toate mesajele

Leave a comment

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *