Bottleneck when receiving UDP packets?

Some useful but linux-specific advice from the Cloudflare blog: How to receive a million packets per second.

On the sending side, I think sleeping after every packet is the issue. the julia sleep function is only accurate to within about 1ms, there’s a usleep function you can Ccall which could be better.

I don’t think this is actually on the receive end, it’s the sending. Just my current guess.

I’d suggest to figure out how many packets you’re supposed to send per 5ms, send those, and then sleep 5ms. yes it’s bursty, but figure even at 100k packets per second, in 5ms we’re only talking 500 packets per loop, and 100k packets per second is crazy high for most purposes. If you’re talking 10k packets per second, you’d be sending 50 packets per time through the loop, then check how long to sleep, then sleep that long, and start over.

EDIT: indeed when I do this:


function send_data(sock, target, port, data, packets_per_second)
    delta_t = 1 / packets_per_second
    stopat = time() + delta_t
    pp5m = round(packets_per_second * 5/1000)
    while true
        now = time()
        for i in 1:pp5m
            send(sock, target, port, data)
        end
        after = time()
        
        pausefor = now + .005 - after
        if pausefor < 0
            # error("Can't keep up with UDP packet rate ($pausefor s)")
            print(".")
            continue
        end
        sleep(pausefor)
    end
end

I have no problem running your sender with 10000 packets per second with no overruns on my linux desktop and the receiver says:

Counting UDP packets for 20 seconds
150601 UDP packets recieved

or about 7500 pps

So it’s not a super accurate method of timing, but basically the issue is that you’re sending one packet and sleeping rather than sleeping less often or calling usleep

@tamasgal

2 Likes

Ah very nice. I was so sure that the sending part is correct, given that I even monitored the time between sending and sleeping and it looked ok.

Thanks :slight_smile:

1 Like

Yeah, for me the clue was that wireshark couldn’t capture the packets. I’ve done packet captures during speed tests at large fractions of a gigabit, so wireshark is capable of tens of thousands of packets per second no issues on my machine. Since you were only seeing a few hundred packets per second, it wasn’t on the receiving end… so then I started looking at the method of sending. Glad we figured it out.

It seems like julia should offer nanosleep: nanosleep(2) - Linux manual page

1 Like

…me looking at the wrong end for days :see_no_evil:

nanosleep sounds interesting indeed