[Twisted-Python] Twisted receiving buffers swamped?

Tobias Oberstein tobias.oberstein at tavendo.de
Thu Jan 1 03:21:55 MST 2015


Hi,

I am doing network performance tests using netperf on a trivial Twisted 
TCP echo server (code at the end).

One of the tests that netperf offers is throughput, and I am running 
into an issue with this.

When running the test (loopback) for 10 seconds on the test box I get a 
throughput of 11.5 Gb/s (which is not bad):

[oberstet at brummer1 ~]$ netperf -N -H 127.0.0.1 -t TCP_STREAM -l 10 -- -P 
9000
TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 9000 AF_INET to 127.0.0.1 () 
port 9000 AF_INET 
         : no control : histogram : interval : dirty data : demo
Recv   Send    Send
Socket Socket  Message  Elapsed
Size   Size    Size     Time     Throughput
bytes  bytes   bytes    secs.    10^6bits/sec

      0  32768  32768    10.02    11517.89

[Sidenote: when running against the netperf server, the box does 46Gb/s 
on that test. More results here: 
https://github.com/crossbario/crossbar/wiki/Stream-Testee#netperf]

However, when I run the test for 60 s (changing to "-l 60" in above will 
do), the test server is killed by the OS due to out-of-memory.

This screenshot

http://picpaste.com/pics/Clipboard03-DllXR7QE.1420107551.png

shows that the server at the time immediately before of killing 
allocated >30GB RAM.

In fact, memory also runs away with 10 sec test .. it's just that the 
machine has enough RAM to cope with that. So it's a "general" issue.

I tested with:

* CPython 2.7.9 and PyPy 2.4
* select, poll and kqueue reactors

all on FreeBSD 10.1. Same behavior for all combinations.

===

Now, my suspicion is that Twisted is reading off the TCP stack from the 
kernel and buffering in userspace faster than the echo server is pushing 
out stuff to the TCP stack into the kernel. Hence, no TCP backpressure 
results, netperf happily sends more and more, and the memory of the 
Twisted process runs away.

I am aware of 
http://twistedmatrix.com/documents/14.0.0/core/howto/producers.html, but 
that seems to cover the sending side only.

What's the cause? What can I do?

How do I prevent Twisted to read off sockets from kernel as the 
userspace buffer grows?

E.g. can I set a limit on the userspace buffer, so Twisted won't read 
out the sockets until the app has consumed more of the already buffered 
stuff?

Any hints appreciated,

Cheers,
/Tobias



TCP Echo Server used ====>

from twisted.internet import kqreactor
kqreactor.install()
#from twisted.internet import selectreactor
#selectreactor.install()
#from twisted.internet import pollreactor
#pollreactor.install()

from twisted.internet import protocol, reactor, endpoints

class Echo(protocol.Protocol):
     def dataReceived(self, data):
         self.transport.write(data)

class EchoFactory(protocol.Factory):
     def buildProtocol(self, addr):
         return Echo()

endpoints.serverFromString(reactor, "tcp:9000").listen(EchoFactory())

print "running on ", reactor.__class__
reactor.run()




More information about the Twisted-Python mailing list