Precise sleep for constant UDP packet rate (minimal jitter) [closed]

For a broadcast video application, we need to send UDP packets at a very precise timing interval: around 200µs

Even after pinning the CPU core, setting the scheduler to SCHED_FIFO setting the priority to 99, we occasionally get a 1ms packet gap (or more). That appears to be from the thread being de-scheduled.

We got much better accuracy by using a busy-wait loop for very low sleep values, but now the CPU usage is 100%.

I’m aware of custom hardware Ethernet cards which implement guaranteed packet transmission but am looking for someway to do it in software with standard NIC cards.

Any suggestions?

The code below is is part of the larger C++ 11 program. Error checking has been removed for brevity.

cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(1, &cpuset); // pin to core 1

pthread_t self = pthread_self();
pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);

struct sched_param schedParam;
schedParam.sched_priority = 99;
pthread_setschedparam(self, schedPolicy, &schedParam);

while (1)
{
    getBuffer(txBuffer);
    sendto(mSockFd, txBuffer.buffer, txBuffer.size, 0,
                    (struct sockaddr *)&mTargetSockAddr, sizeof(struct sockaddr));
    wait();
}

void wait()
{
    int sleepUsec = getSleepTime(); // returns 200
    
    struct timespec sleepStartTime;
    clock_gettime(CLOCK_MONOTONIC_RAW, &sleepStartTime);

    int elapsedUsec = 0;
    while (elapsedUsec < requiredSleepUsec)
    {
        // busy spin if low value
        if (sleepUsec < 500)
        {
            u_int total = 0;
            for (int i = 0; i < 100; i++)
                total += M_PI * rand();
        }
        else
            usleep(sleepUsec);

        clock_gettime(CLOCK_MONOTONIC_RAW, &nowTime);
        elapsedUsec = (nowTime.tv_sec - sleepStartTime.tv_sec) * 1000000 + (nowTime.tv_nsec - sleepStartTime.tv_nsec) / 1000;
        sleepUsec   = (requiredSleepUsec - elapsedUsec) / 2;

    }
}

Environment is Centos 8

  • 2

    Please post the real code instead of the pseudo code since the pseudo code has logic flaws and doesn’t work.

    – 

  • 2

    Don’t mix C and C++ tags, solutions are different.

    – 

  • Real code uploaded, tag updated for C++

    – 




  • Maybe dedicate a core and run it from a timer interrupt in the kernel. Any userspace program can suffer delays. Why are you not buffering at the receiver?

    – 

  • We have on control over the downstream equipment. It doesn’t buffer well so the inter-packet timing has to be very precise. Does “dedicate a core” mean run it outside of the OS?

    – 

Leave a Comment