Поток, который спит в течение X миллисекунд, не гарантированно спит именно столько миллисекунд. Я предполагаю, что у вас есть утверждение, которое выглядит примерно так:
while(1) {
...
sleep(10); // Sleep for 10 seconds.
// fetch timestamp and send
}
Вы получите более точный показатель времени, если будете спать в течение более коротких периодов (скажем, 20 миллисекунд) в циклической проверке до истечения времени. Когда вы спите в течение 10 секунд, ваш поток перемещается дальше от непосредственного приоритета планирования базовой ОС.
Вы также можете принять во внимание, что время, необходимое для отправки меток времени, может варьироваться в зависимости от состояния сети и т. Д., Если вы делаете цикл sleep (10) -> send -> sleep (10), время взятые для отправки будут добавлены в следующий сон (10) в реальном выражении.
Попробуйте что-то вроде этого (прости меня, мой C немного ржавый):
bool expired = false;
double last, current;
double t1, t2;
double difference = 0;
while(1) {
...
last = (double)clock();
while(!expired) {
usleep(200); // sleep for 20 milliseconds
current = (double)clock();
if(((current - last) / (double)CLOCKS_PER_SEC) >= (10.0 - difference))
expired = true;
}
t1 = (double)clock();
// Set and send the timestamp.
t2 = (double)clock();
//
// Calculate how long it took to send the stamps.
// and take that away from the next sleep cycle.
//
difference = (t2 - t1) / (double)CLOCKS_PER_SEC;
expired = false;
}
Если вас не беспокоит использование стандартной библиотеки C, вы можете посмотреть на использование функций таймера высокого разрешения для окон, таких как функции QueryPerformanceFrequency / QueryPerformanceCounter.
LONG_INTEGER freq;
LONG_INTEGER t2, t1;
//
// Get the resolution of the timer.
//
QueryPerformanceFrequency(&freq);
// Start Task.
QueryPerformanceCounter(&t1);
... Do something ....
QueryPerformanceCounter(&t2);
// Very accurate duration in seconds.
double duration = (double)(t2.QuadPart - t1.QuadPart) / (double)freq.QuadPart;