By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,270 Members | 1,703 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,270 IT Pros & Developers. It's quick & easy.

Re: Problem with writing fast UDP server

P: n/a
On Fri, 21 Nov 2008 00:20:49 -0200, Gabriel Genellina <ga*******@yahoo.com.arwrote:
>En Thu, 20 Nov 2008 14:24:20 -0200, Krzysztof Retel
<Kr*************@googlemail.comescribió:
>>On Nov 20, 4:00Â*pm, bieff...@gmail.com wrote:
>>>On 20 Nov, 16:03, Krzysztof Retel <Krzysztof.Re...@googlemail.com>
wrote:

I am struggling writing fast UDP server. It has to handle around 10000
UDP packets per second. I started building that with non blocking
socket and threads. Unfortunately my approach does not work at all.
I wrote a simple case test: client and server. The client sends 2200
packets within 0.137447118759 secs. The tcpdump received 2189 packets,
which is not bad at all.
But the server only handles 700 -- 870 packets, when it is non-
blocking, and only 670 – 700 received with blocking sockets.
The client and the server are working within the same local network
and tcpdump shows pretty correct amount of packets received.

I wonder if there is a kind of setting for socket to allow no delays?

I've used this script to test sending UDP packets. I've not seen any
delays.

<code>
[snip]
</code>

Start the server before the client.
If you want to try this program out on POSIX, make sure you change the
time.clock() calls to time.time() calls instead, otherwise the results
aren't very meaningful.

I gave this a try on an AMD64 3200+ running a 32 bit Linux installation.
Here's the results I got on the server:

Packet count 91426
Total bytes 8228340 bytes
Total time 8.4 secs
Avg size / packet 90 bytes
Max size / packet 90 bytes
Max time / packet 41070.9 us
Min time / packet 79.9 us
Avg time / packet 92.3 us
Max speed 1100.4 Kbytes/sec
Min speed 2.1 Kbytes/sec
Avg speed 952.0 Kbytes/sec

And on the client:

Packet count 91426
Total bytes 8228340 bytes
Total time 8.4 secs
Avg size / packet 90 bytes
Max size / packet 90 bytes
Max time / packet 40936.0 us
Min time / packet 78.9 us
Avg time / packet 92.3 us
Max speed 1113.7 Kbytes/sec
Min speed 2.1 Kbytes/sec
Avg speed 952.1 Kbytes/sec

Both processes ran on the same machine and communicated over localhost.

For comparison, I tried running the client against a Twisted-based UDP
server. Here are the results from that server:

Packet count 91426
Total bytes 8228340 bytes
Total time 11.8 secs
Avg size / packet 90 bytes
Max size / packet 90 bytes
Max time / packet 55393.9 us
Min time / packet 8.8 us
Avg time / packet 128.7 us
Max speed 9963.2 Kbytes/sec
Min speed 1.6 Kbytes/sec
Avg speed 682.7 Kbytes/sec

This seemed a bit low to me though, so I tried writing an alternate client
and re-ran the measurement. Here are the new server results:

Packet count 91426
Total bytes 8228340 bytes
Total time 2.9 secs
Avg size / packet 90 bytes
Max size / packet 90 bytes
Max time / packet 38193.0 us
Min time / packet 8.8 us
Avg time / packet 32.2 us
Max speed 9963.2 Kbytes/sec
Min speed 2.3 Kbytes/sec
Avg speed 2726.7 Kbytes/sec

And then tried the new client against the original server, with these
results:

Packet count 91426
Total bytes 8228340 bytes
Total time 3.8 secs
Avg size / packet 90 bytes
Max size / packet 90 bytes
Max time / packet 23675.0 us
Min time / packet 6.9 us
Avg time / packet 41.7 us
Max speed 12711.7 Kbytes/sec
Min speed 3.7 Kbytes/sec
Avg speed 2109.0 Kbytes/sec

So it does seem that handling 10k datagrams per second should be no
problem, assuming comparable hardware, at least if whatever work you
have to do to process each one doesn't take more than about 24 25ths
of a millisecond (leaving you the remaining 1 part out of 25 of every
millisecond to receive a packet).

For reference, here's the Twisted UDP client code:

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.internet.task import LoopingCall

msg = 'xyxabc123' * 10

class EchoClientDatagramProtocol(DatagramProtocol):

def startProtocol(self):
self.transport.connect('127.0.0.1', 8000)
LoopingCall(self.sendDatagrams).start(0.00005)

def sendDatagrams(self):
for i in xrange(50):
self.transport.write(msg)

def main():
protocol = EchoClientDatagramProtocol()
t = reactor.listenUDP(0, protocol)
reactor.run()

if __name__ == '__main__':
main()

And here's the Twisted UDP server code:

from time import time as clock

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor

class EchoUDP(DatagramProtocol):
history = []
t0 = clock()
def datagramReceived(self, datagram, address):
t1 = clock()
self.history.append((len(datagram), t1 - self.t0))
self.t0 = t1
if len(self.history) == 91427:
self.history.pop(0)
show_stats(self.history)
self.history = []

def main():
reactor.listenUDP(8000, EchoUDP())
reactor.run()

def show_stats(history):
npackets = len(history)
bytes_total = sum([item[0] for item in history])
bytes_avg = float(bytes_total) / npackets
bytes_max = max([item[0] for item in history])
time_total = sum([item[1] for item in history])
time_max = max([item[1] for item in history])
time_min = min([item[1] for item in history])
time_avg = float(time_total) / npackets
speed_max = max([item[0]/item[1] for item in history if item[1]>0])
speed_min = min([item[0]/item[1] for item in history if item[1]>0])
speed_avg = float(bytes_total) / time_total
print "Packet count %8d" % npackets
print "Total bytes %8d bytes" % bytes_total
print "Total time %8.1f secs" % time_total
print "Avg size / packet %8d bytes" % bytes_avg
print "Max size / packet %8d bytes" % bytes_max
print "Max time / packet %8.1f us" % (time_max*1e6)
print "Min time / packet %8.1f us" % (time_min*1e6)
print "Avg time / packet %8.1f us" % (time_avg*1e6)
print "Max speed %8.1f Kbytes/sec" % (speed_max/1024)
print "Min speed %8.1f Kbytes/sec" % (speed_min/1024)
print "Avg speed %8.1f Kbytes/sec" % (speed_avg/1024)
print

if __name__ == '__main__':
main()

Nov 21 '08 #1
Share this Question
Share on Google+
1 Reply


P: n/a
On Nov 21, 3:52*am, Jean-Paul Calderone <exar...@divmod.comwrote:
>
Start the server before the client.

If you want to try this program out on POSIX, make sure you change the
time.clock() calls to time.time() calls instead, otherwise the results
aren't very meaningful.

I gave this a try on an AMD64 3200+ running a 32 bit Linux installation.
Here's the results I got on the server:
Jean-Paul, thanks very much for the code snippets.
I have tried this out with number of tests. Both approaches are
working fine when I run them on the same machine.
When I run the client (twisted version) on another machine and the udp
server (non twisted) on server machine, I got some strange behaviour.
The client send 255 messages and than it cause an error: socket.error:
(11, 'Resource temporarily unavailable')

Any idea what could be wrong?

Nov 21 '08 #2

This discussion thread is closed

Replies have been disabled for this discussion.