Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

udp rate limits in python?

Tags:

python

udp

Update to original post: A colleague pointed out what I was doing wrong. I'll give the explanation at the bottom of the post, as it might be helpful for others.


I am trying to get a basic understanding of the limits on network performance of python programs and have run into an anomaly. The code fragment

while 1:
    sock.sendto("a",target)

sends UDP packets to a target machine, as fast as the host will send. I measure a sending rate of just over 4000 packets per second, or 250 us per packet. This seems slow, even for an interpreted language like python (the program is running on a 2 GHz AMD opteron, Linux, python version 2.6.6). I've seen much better performance in python for TCP, so I find this a bit weird.

If I run this in the background and run top, I find that python is using just 25% of the cpu, suggesting that python may be artificially delaying the transmission of UDP packets.

Has anyone else experienced anything similar? Does anyone know if python does limit the rate of packet transmission, and if there is a way to turn this off?

BTW, a similar C++ program can send well over 200,000 packets per second, so it's not an intrinsic limit of the platform or OS.


So, it turns out I made a silly newbie mistake. I neglected to call gethostbyname explicitly. Consequently, the target address in the sendto command contained a symbolic name. This was triggering a name resolution every time a packet was sent. After fixing this, I measure a maximum sending rate of about 120,000 p/s. Much better.

like image 269
user1644373 Avatar asked Sep 03 '12 18:09

user1644373


2 Answers

You might want to post a more complete code sample so that others can repeat your benchmark. 250μs per loop iteration is too slow. Based on daily experience with optimizing Python, I would expect Python's interpreter overhead to be well below 1μs on a modern machine. In other words, if the C++ program is sending 200k packets per second, I would expect Python to be in the same order of magnitude of speed.

(In light of the above, the usual optimization suggestions such as moving the attribute lookup of sock.sendto out of the loop do not apply here because the slowness is coming from another source.)

A good first step to be to use strace to check what Python is actually doing. Is it a single-threaded program or a multithreaded application that might be losing time waiting on the GIL? Is sock a normal Python socket or is it part of a more elaborate API? Does the same happen when you directly call os.write on the socket's fileno?

like image 127
user4815162342 Avatar answered Oct 11 '22 21:10

user4815162342


Have you tried doing a connect() first, then using send() instead of sendto()? (UDP connect() just establishes the destination address, it doesn't actually make a "connection".) I'm rusty on this, but I believe Python does more interpretation on the address parameter than C sockets, which might be adding overhead.

like image 43
Russell Borogove Avatar answered Oct 11 '22 22:10

Russell Borogove