[Twisted-Python] Advise for heavy concurrency
![](https://secure.gravatar.com/avatar/b767aad6ee69a38bdd7702ad540beb00.jpg?s=120&d=mm&r=g)
I'm interested in how well Twisted would perform in situations where there is a very high number of concurrent connections. The problem: I'm working on a feature that would require me to distribute small amounts, both in occurrence and size, of packets to a very large number of connected clients. Think in the terms of a Jabber or IRC server, but with a lot less traffic. What we're trying to do is to maximize the number of simultaneous connections a server can run, to an absolute maximum. It'll be a dedicated system so crippling any system-wide setting is not going to interfere with other applications. So far experimenting with the epoll reactor has shown really nice scalability as numbers grow. Thousands of connections per machine are no problem at all, but we need to scale out heavily. At a certain point the memory requirements for keeping open all those connections in the system grow higher, but those can be minimized by adjusting system buffer sizes, tcp window sizes and certain other settings. Furthermore - more than one instance of the service could be ran per server, dedicating two or three processes on a 4-core CPU system, until exhausting the rest of the limits, in case CPU oevrhead becomes large. I'm also considering advantages that might come through different I/O and/or process schedulers. Is there anything that would be beneficial to my situation, considering the server will be a dedicated machine with little to nothing else to run on it that might suffer performance degradation? Does anyone have any experience with scaling twisted to a very large number of parallel connections? Are there any limitations that I might be missing? We'll start experimenting with a sample service soon to try to identify any specific limitations that will need to be worked on. Any tips are wellcome. Cheers,
![](https://secure.gravatar.com/avatar/45c4c3d016586cd3f4f3adcc3f0c104d.jpg?s=120&d=mm&r=g)
Here is one tip: If you have a dual Xeon 5140 (4 cores) machine and run 4 twisted epoll servers in a similar (but not exactly similar situation), it chokes at 30000 clients. The machine is CPU-bound, and the for loop that loops over clients to send your packets is a performance hog. We are now considering using pyrex for that for loop, or rewriting it with C and libevent.
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python- bounces@twistedmatrix.com] On Behalf Of Atilla Sent: Wednesday, November 28, 2007 3:34 PM To: Twisted general discussion Subject: [Twisted-Python] Advise for heavy concurrency
I'm interested in how well Twisted would perform in situations where there is a very high number of concurrent connections.
The problem: I'm working on a feature that would require me to distribute small amounts, both in occurrence and size, of packets to a very large number of connected clients. Think in the terms of a Jabber or IRC server, but with a lot less traffic. What we're trying to do is to maximize the number of simultaneous connections a server can run, to an absolute maximum. It'll be a dedicated system so crippling any system-wide setting is not going to interfere with other applications.
So far experimenting with the epoll reactor has shown really nice scalability as numbers grow. Thousands of connections per machine are no problem at all, but we need to scale out heavily.
At a certain point the memory requirements for keeping open all those connections in the system grow higher, but those can be minimized by adjusting system buffer sizes, tcp window sizes and certain other settings.
Furthermore - more than one instance of the service could be ran per server, dedicating two or three processes on a 4-core CPU system, until exhausting the rest of the limits, in case CPU oevrhead becomes large.
I'm also considering advantages that might come through different I/O and/or process schedulers. Is there anything that would be beneficial to my situation, considering the server will be a dedicated machine with little to nothing else to run on it that might suffer performance degradation?
Does anyone have any experience with scaling twisted to a very large number of parallel connections? Are there any limitations that I might be missing?
We'll start experimenting with a sample service soon to try to identify any specific limitations that will need to be worked on.
Any tips are wellcome. Cheers,
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
![](https://secure.gravatar.com/avatar/4e1ae4b836a9cfe3945d8c661b37246b.jpg?s=120&d=mm&r=g)
Alec Matusis ha scritto:
Here is one tip:
If you have a dual Xeon 5140 (4 cores) machine and run 4 twisted epoll servers in a similar (but not exactly similar situation), it chokes at 30000 clients.
The machine is CPU-bound, and the for loop that loops over clients to send your packets is a performance hog. We are now considering using pyrex for that for loop, or rewriting it with C and libevent.
You can also consider nginx, if you want to write a server in C (or in the D language). It is a web server, but its core is usable as a framework for generic servers (in fact nginx has also a POP3/IMAP4 proxy server). nginx has many appealing features, like integrated garbage collector, and multi process workers. Manlio Perillo
![](https://secure.gravatar.com/avatar/b767aad6ee69a38bdd7702ad540beb00.jpg?s=120&d=mm&r=g)
I doubt I'll be running 4 heavy cpu-bound processes on a 4-core system, I'd prefer to leave 1 core "free" for all the rest of monitoring/logging tasks. What causes the CPU overload in such a case? Currently I keep a custom many-to-many like structure, which has O(1) access time and need to forward the same message to N clients that are returned from that structure, for each incoming packet, at worst. I could potentially pre-pack the exact network message to avoid generating it for each of them, which at this point is the largest overhead. Although I'm not sure how much I can save like that.
![](https://secure.gravatar.com/avatar/45c4c3d016586cd3f4f3adcc3f0c104d.jpg?s=120&d=mm&r=g)
What causes the CPU overload in such a case
It looks like the for loop that loops over connections to send the message is the main source of the load. The biggest problem is not the CPU however. When the process takes more than 70% of the CPU (as displayed by top), python seems to start skipping garbage collection, and the memory size of the process just keeps growing. We have no control over this.
I doubt I'll be running 4 heavy cpu-bound processes on a 4-core system
Running 4 servers on a 4-core box seems fine, it leaves plenty of resources for system tasks and logging, as long as as long as they are not at 99% CPU each, but I doubt you will get them to run at 99% because of the said memory problem.
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python- bounces@twistedmatrix.com] On Behalf Of Atilla Sent: Thursday, November 29, 2007 10:47 AM To: Twisted general discussion Subject: Re: [Twisted-Python] Advise for heavy concurrency
I doubt I'll be running 4 heavy cpu-bound processes on a 4-core system, I'd prefer to leave 1 core "free" for all the rest of monitoring/logging tasks.
What causes the CPU overload in such a case? Currently I keep a custom many-to-many like structure, which has O(1) access time and need to forward the same message to N clients that are returned from that structure, for each incoming packet, at worst. I could potentially pre-pack the exact network message to avoid generating it for each of them, which at this point is the largest overhead. Although I'm not sure how much I can save like that.
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
![](https://secure.gravatar.com/avatar/4e1ae4b836a9cfe3945d8c661b37246b.jpg?s=120&d=mm&r=g)
Alec Matusis ha scritto:
What causes the CPU overload in such a case
It looks like the for loop that loops over connections to send the message is the main source of the load. The biggest problem is not the CPU however. When the process takes more than 70% of the CPU (as displayed by top), python seems to start skipping garbage collection, and the memory size of the process just keeps growing. We have no control over this.
You should break the loop into small parts. If you send a message to a lot of clients, then Twisted needs to keep all the buffers in memory (since your loop is blocking the reactor and Twisted is unable to flush the buffers). You see the memory growing because the Python interpreter will not release the memory to the operating system (however the memory should not grow indefinitely)
[...]
Manlio Perillo
![](https://secure.gravatar.com/avatar/45c4c3d016586cd3f4f3adcc3f0c104d.jpg?s=120&d=mm&r=g)
You should break the loop into small parts.
Can you explain this? Do you mean, use reactor.callLater to process say 100 messages at a time? Or maybe use deferToThread for the whole loop?
You see the memory growing because the Python interpreter will not release the memory to the operating system (however the memory should not grow indefinitely)
The memory is actually growing indefinitely. We run 4 identical servers on one machine. The load is not balanced very symmetrically. So one server can have 4500 connections, while another has 6000. There is a certain threshold on the number of connections, when a server starts to leak memory uncontrollably, and it's not set by the highest usage. For example, a server with 4500 connections remains at 100mb RSS for days, while a server that reaches 6000 connections leaks memory to 2gb in 10 hrs (I did not try beyond that, since the machine starts swapping!)
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python- bounces@twistedmatrix.com] On Behalf Of Manlio Perillo Sent: Saturday, December 01, 2007 2:06 AM To: Twisted general discussion Subject: Re: [Twisted-Python] Advise for heavy concurrency
Alec Matusis ha scritto:
What causes the CPU overload in such a case
It looks like the for loop that loops over connections to send the message is the main source of the load. The biggest problem is not the CPU however. When the process takes more than 70% of the CPU (as displayed by top), python seems to start skipping garbage collection, and the memory size of the process just keeps growing. We have no control over this.
You should break the loop into small parts.
If you send a message to a lot of clients, then Twisted needs to keep all the buffers in memory (since your loop is blocking the reactor and Twisted is unable to flush the buffers).
You see the memory growing because the Python interpreter will not release the memory to the operating system (however the memory should not grow indefinitely)
[...]
Manlio Perillo
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
![](https://secure.gravatar.com/avatar/4e1ae4b836a9cfe3945d8c661b37246b.jpg?s=120&d=mm&r=g)
Alec Matusis ha scritto:
You should break the loop into small parts.
Can you explain this? Do you mean, use reactor.callLater to process say 100 messages at a time? Or maybe use deferToThread for the whole loop?
There is also twisted.internet.task.cooperate, but I have never used it.
You see the memory growing because the Python interpreter will not release the memory to the operating system (however the memory should not grow indefinitely)
The memory is actually growing indefinitely. We run 4 identical servers on one machine. The load is not balanced very symmetrically. So one server can have 4500 connections, while another has 6000. There is a certain threshold on the number of connections, when a server starts to leak memory uncontrollably, and it's not set by the highest usage. For example, a server with 4500 connections remains at 100mb RSS for days, while a server that reaches 6000 connections leaks memory to 2gb in 10 hrs (I did not try beyond that, since the machine starts swapping!)
How big is a message sent to each client? That is, how much memory requires to hold all these messages in memory?
[...]
P.S.: your mail user agent does not wraps long lines; can you please fix it? Manlio Perillo
![](https://secure.gravatar.com/avatar/45c4c3d016586cd3f4f3adcc3f0c104d.jpg?s=120&d=mm&r=g)
How big is a message sent to each client?
Each message is about 40 bytes. A typical loop to send message is 1000 clients, so only 40KB to hold the message for all clients.
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python- bounces@twistedmatrix.com] On Behalf Of Manlio Perillo Sent: Saturday, December 01, 2007 3:55 AM To: Twisted general discussion Subject: Re: [Twisted-Python] Advise for heavy concurrency
Alec Matusis ha scritto:
You should break the loop into small parts.
Can you explain this? Do you mean, use reactor.callLater to process say 100 messages at a time? Or maybe use deferToThread for the whole loop?
There is also twisted.internet.task.cooperate, but I have never used it.
You see the memory growing because the Python interpreter will not release the memory to the operating system (however the memory should not grow indefinitely)
The memory is actually growing indefinitely. We run 4 identical servers on one machine. The load is not balanced very symmetrically. So one server can have 4500 connections, while another has 6000. There is a certain threshold on the number of connections, when a server starts to leak memory uncontrollably, and it's not set by the highest usage. For example, a server with 4500 connections remains at 100mb RSS for days, while a server that reaches 6000 connections leaks memory to 2gb in 10 hrs (I did not try beyond that, since the machine starts swapping!)
How big is a message sent to each client? That is, how much memory requires to hold all these messages in memory?
[...]
P.S.: your mail user agent does not wraps long lines; can you please fix it?
Manlio Perillo
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
![](https://secure.gravatar.com/avatar/b767aad6ee69a38bdd7702ad540beb00.jpg?s=120&d=mm&r=g)
I think I can control a lot of the memory overhead, both the one in my application and the one that comes with the OSs overhead for the TCP stack and network bufers. I've yet to see how much memory that is going to take. When it comes to deferToThread - is that actually going to be of any use? Do I get an advantage of running the "send" loop in a seperate thread? What if, say, I never had to send more than 10-50 messages, so the loop is relatively small - then I'd have to keep spawning threads for no reason. But - when it comes to large send queues, how can that be chopped in an efficient manner? Chop it into equal pieces and schedule them with small delay, one after the other? Defer them to another thread? Is there any other solution, a way to chain them into a log callback squence maybe?
![](https://secure.gravatar.com/avatar/82ac0220d0d1caa3cba717e7bbd42318.jpg?s=120&d=mm&r=g)
* Atilla <theatilla@gmail.com> [2007-12-02 00:37:47 +0100]:
When it comes to deferToThread - is that actually going to be of any use? Do I get an advantage of running the "send" loop in a seperate thread? What if, say, I never had to send more than 10-50 messages, so
You cannot call any Twisted functions from a thread, with the exception of callFromThread; so this would probably be pretty pointless. -- mithrandi, i Ainil en-Balandor, a faer Ambar
![](https://secure.gravatar.com/avatar/82ac0220d0d1caa3cba717e7bbd42318.jpg?s=120&d=mm&r=g)
* Tristan Seligmann <mithrandi@mithrandi.za.net> [2007-12-02 04:50:44 +0200]:
* Atilla <theatilla@gmail.com> [2007-12-02 00:37:47 +0100]:
When it comes to deferToThread - is that actually going to be of any use? Do I get an advantage of running the "send" loop in a seperate thread? What if, say, I never had to send more than 10-50 messages, so
You cannot call any Twisted functions from a thread, with the exception ^^^^^^^^^^^^^ Er, I guess I should have worded this more carefully. What I meant is: you cannot call any Twisted functions from a different thread to the one the reactor is running in, which includes any thread created with deferToThread.
of callFromThread; so this would probably be pretty pointless. -- mithrandi, i Ainil en-Balandor, a faer Ambar
![](https://secure.gravatar.com/avatar/45c4c3d016586cd3f4f3adcc3f0c104d.jpg?s=120&d=mm&r=g)
You cannot call any Twisted functions from a thread, with the exception ^^^^^^^^^^^^^ Er, I guess I should have worded this more carefully. What I meant is: you cannot call any Twisted functions from a different thread to the one the reactor is running in, which includes any thread created with deferToThread.
of callFromThread; so this would probably be pretty pointless.
I am not sure I understood this: suppose my message sending loop simply loops over client protocol instances and calls transport.write(some_message) Why cannot I call this loop in a thread from the main reactor loop to have it non-blocking in case this sending loop is giant (over 1000s of clients)? I do not care when this sending loop is finished, I just do not want this to slow down the main reactor loop. With 50 clients this is obviously unnecessary.
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python- bounces@twistedmatrix.com] On Behalf Of Tristan Seligmann Sent: Saturday, December 01, 2007 6:57 PM To: twisted-python@twistedmatrix.com Subject: Re: [Twisted-Python] Advise for heavy concurrency
* Tristan Seligmann <mithrandi@mithrandi.za.net> [2007-12-02 04:50:44 +0200]:
* Atilla <theatilla@gmail.com> [2007-12-02 00:37:47 +0100]:
When it comes to deferToThread - is that actually going to be of any use? Do I get an advantage of running the "send" loop in a seperate thread? What if, say, I never had to send more than 10-50 messages, so
You cannot call any Twisted functions from a thread, with the exception ^^^^^^^^^^^^^ Er, I guess I should have worded this more carefully. What I meant is: you cannot call any Twisted functions from a different thread to the one the reactor is running in, which includes any thread created with deferToThread.
of callFromThread; so this would probably be pretty pointless. -- mithrandi, i Ainil en-Balandor, a faer Ambar
![](https://secure.gravatar.com/avatar/7ed9784cbb1ba1ef75454034b3a8e6a1.jpg?s=120&d=mm&r=g)
On Sat, 1 Dec 2007 19:40:28 -0800, Alec Matusis <matusis@yahoo.com> wrote:
You cannot call any Twisted functions from a thread, with the exception ^^^^^^^^^^^^^ Er, I guess I should have worded this more carefully. What I meant is: you cannot call any Twisted functions from a different thread to the one the reactor is running in, which includes any thread created with deferToThread.
of callFromThread; so this would probably be pretty pointless.
I am not sure I understood this: suppose my message sending loop simply loops over client protocol instances and calls transport.write(some_message)
Why cannot I call this loop in a thread from the main reactor loop to have it non-blocking in case this sending loop is giant (over 1000s of clients)?
Because it is not a supported use of the API. Twisted APIs, unless other- wise documented, are not thread safe and can only be called from the thread in which the reactor is running. Jean-Paul
![](https://secure.gravatar.com/avatar/45c4c3d016586cd3f4f3adcc3f0c104d.jpg?s=120&d=mm&r=g)
Because it is not a supported use of the API. Twisted APIs, unless other- wise documented, are not thread safe and can only be called from the thread in which the reactor is running.
Then I do not understand when it is safe to use t.i.threads.deferToThread(f, clients) ? I was thinking of calling this from the main reactor thread, where f is def f(clients): for client in clients: client.protocol.transport.write('hello') This function would not even have a deferred attached to it. Is the point that it's not thread-safe to have Twisted API calls inside the function f?
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python- bounces@twistedmatrix.com] On Behalf Of Jean-Paul Calderone Sent: Saturday, December 01, 2007 10:25 PM To: Twisted general discussion Subject: RE: [Twisted-Python] Advise for heavy concurrency
On Sat, 1 Dec 2007 19:40:28 -0800, Alec Matusis <matusis@yahoo.com> wrote:
You cannot call any Twisted functions from a thread, with the exception ^^^^^^^^^^^^^ Er, I guess I should have worded this more carefully. What I meant is: you cannot call any Twisted functions from a different thread to the one the reactor is running in, which includes any thread created with deferToThread.
of callFromThread; so this would probably be pretty pointless.
I am not sure I understood this: suppose my message sending loop simply loops over client protocol instances and calls transport.write(some_message)
Why cannot I call this loop in a thread from the main reactor loop to have it non-blocking in case this sending loop is giant (over 1000s of clients)?
Because it is not a supported use of the API. Twisted APIs, unless other- wise documented, are not thread safe and can only be called from the thread in which the reactor is running.
Jean-Paul
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
![](https://secure.gravatar.com/avatar/45c4c3d016586cd3f4f3adcc3f0c104d.jpg?s=120&d=mm&r=g)
PS. Sorry I forgot:
t.i.threads.deferToThread(f, clients) ?
I suppose my question also applies to twisted.internet.reactor.callInThread(f, clients)
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python- bounces@twistedmatrix.com] On Behalf Of Alec Matusis Sent: Saturday, December 01, 2007 11:27 PM To: 'Twisted general discussion' Subject: RE: [Twisted-Python] Advise for heavy concurrency
Because it is not a supported use of the API. Twisted APIs, unless other- wise documented, are not thread safe and can only be called from the thread in which the reactor is running.
Then I do not understand when it is safe to use
t.i.threads.deferToThread(f, clients) ?
I was thinking of calling this from the main reactor thread, where f is
def f(clients): for client in clients: client.protocol.transport.write('hello')
This function would not even have a deferred attached to it. Is the point that it's not thread-safe to have Twisted API calls inside the function f?
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted- python- bounces@twistedmatrix.com] On Behalf Of Jean-Paul Calderone Sent: Saturday, December 01, 2007 10:25 PM To: Twisted general discussion Subject: RE: [Twisted-Python] Advise for heavy concurrency
On Sat, 1 Dec 2007 19:40:28 -0800, Alec Matusis <matusis@yahoo.com> wrote:
You cannot call any Twisted functions from a thread, with the exception ^^^^^^^^^^^^^ Er, I guess I should have worded this more carefully. What I meant is: you cannot call any Twisted functions from a different thread to the one the reactor is running in, which includes any thread created with deferToThread.
of callFromThread; so this would probably be pretty pointless.
I am not sure I understood this: suppose my message sending loop simply loops over client protocol instances and calls transport.write(some_message)
Why cannot I call this loop in a thread from the main reactor loop to have it non-blocking in case this sending loop is giant (over 1000s of clients)?
Because it is not a supported use of the API. Twisted APIs, unless other- wise documented, are not thread safe and can only be called from the thread in which the reactor is running.
Jean-Paul
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
![](https://secure.gravatar.com/avatar/82ac0220d0d1caa3cba717e7bbd42318.jpg?s=120&d=mm&r=g)
* Alec Matusis <matusis@yahoo.com> [2007-12-01 23:26:38 -0800]:
Because it is not a supported use of the API. Twisted APIs, unless other- wise documented, are not thread safe and can only be called from the thread in which the reactor is running.
Then I do not understand when it is safe to use
t.i.threads.deferToThread(f, clients) ?
The code in f, or in functions called from f, must not invoke any functions in the Twisted API other than reactor.callFromThread. The same goes for a thread created any other way (eg. with callInThread).
I was thinking of calling this from the main reactor thread, where f is
def f(clients): for client in clients: client.protocol.transport.write('hello')
This function would not even have a deferred attached to it. Is the point that it's not thread-safe to have Twisted API calls inside the function f?
Yes, that is basically the point; the only API that is thread-safe is callFromThread; any other Twisted function must be invoked from the reactor thread. If this loop is really blocking for too long, you could use something like the following, which cooperatively distributes the work over several timeslices; you'll need to check that the default scheduler performs the work fast enough for your purposes, though. from twisted.internet.task import coiterate def f(clients): for client in clients: client.protocol.transport.write('hello') yield None coiterate(f) -- mithrandi, i Ainil en-Balandor, a faer Ambar
![](https://secure.gravatar.com/avatar/b767aad6ee69a38bdd7702ad540beb00.jpg?s=120&d=mm&r=g)
Thanks a lot for the feedback, it really cleared some things up. I'll experiment a little with the coiterate and I'll see how it works out for me. My send queues are not going to be large, but they could theoretically grow to large numbers and under heavy load it'll start to matter.
![](https://secure.gravatar.com/avatar/4e1ae4b836a9cfe3945d8c661b37246b.jpg?s=120&d=mm&r=g)
Atilla ha scritto:
Thanks a lot for the feedback, it really cleared some things up. I'll experiment a little with the coiterate and I'll see how it works out for me. My send queues are not going to be large, but they could theoretically grow to large numbers and under heavy load it'll start to matter.
Have you tried to use Python 2.5? Manlio Perillo
![](https://secure.gravatar.com/avatar/3b1704542e4ad7f5fb303b631be59d71.jpg?s=120&d=mm&r=g)
Atilla wrote:
When it comes to deferToThread - is that actually going to be of any use? Do I get an advantage of running the "send" loop in a seperate thread? What if, say, I never had to send more than 10-50 messages, so the loop is relatively small - then I'd have to keep spawning threads for no reason.
Exactly, no reason. Don't spawn threads, unless you have no other way.
But - when it comes to large send queues, how can that be chopped in an efficient manner? Chop it into equal pieces and schedule them with small delay, one after the other?
Yes, and the delay can be very small. Send 50-100 messages at a time, then run the next batch with a reactor.callLater(0.00000001, ...). That way the reactor will be able to handle network events with low latency. Or just use coiterate, as Manlio said: http://twistedmatrix.com/documents/current/api/twisted.internet.task.html It works in 10ms batches: that's your latency. It also uses a 10us delay on the callLater.
Defer them to another thread?
Don't. Only use threads in Twisted if you have to call external, synchronous libraries, like database clients. -- Nicola Larosa - http://www.tekNico.net/ Restricting yourself to the intersection of the two versions [Python 2.6 and 3.0] is very painful and limited. We're not introducing backwards compatibility syntax in 3.0, because that would defeat the purpose (we've had backwards compatibility forever in 2.x, and the whole point of 3.0 is to clean up the mess). -- Guido van Rossum, July 2007
![](https://secure.gravatar.com/avatar/d6328babd9f9a98ecc905e1ccac2495e.jpg?s=120&d=mm&r=g)
On 1 Dec, 11:37 pm, theatilla@gmail.com wrote:
But - when it comes to large send queues, how can that be chopped in an efficient manner? Chop it into equal pieces and schedule them with small delay, one after the other? Defer them to another thread? Is there any other solution, a way to chain them into a log callback squence maybe?
You probably want to use the producer/consumer API. self.transport will provide this interface: http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.I... which will all you to create and send the data only as needed, rather than on a timer. If your concern is the loop over all of your clients, then coiterate might be a better bet, but IConsumer will help you spend that CPU only when you actually need to.
![](https://secure.gravatar.com/avatar/3b1704542e4ad7f5fb303b631be59d71.jpg?s=120&d=mm&r=g)
Manlio Perillo wrote:
You see the memory growing because the Python interpreter will not release the memory to the operating system
This was true until CPython 2.4: the 2.5 version does actually release unused memory to the operating system. Python Memory Management Part 3: The Saga is Over http://evanjones.ca/python-memory-part3.html -- Nicola Larosa - http://www.tekNico.net/ Restricting yourself to the intersection of the two versions [Python 2.6 and 3.0] is very painful and limited. We're not introducing backwards compatibility syntax in 3.0, because that would defeat the purpose (we've had backwards compatibility forever in 2.x, and the whole point of 3.0 is to clean up the mess). -- Guido van Rossum, July 2007
![](https://secure.gravatar.com/avatar/45c4c3d016586cd3f4f3adcc3f0c104d.jpg?s=120&d=mm&r=g)
You can also consider nginx, if you want to write a server in C (or in the D language). It is a web server, but its core is usable as a framework for generic servers (in fact nginx has also a POP3/IMAP4 proxy server).
Do you know if anybody has written general-purpose TCP servers using nginx? It would be interesting to look at.
-----Original Message----- From: twisted-python-bounces@twistedmatrix.com [mailto:twisted-python- bounces@twistedmatrix.com] On Behalf Of Manlio Perillo Sent: Thursday, November 29, 2007 1:31 AM To: Twisted general discussion Subject: Re: [Twisted-Python] Advise for heavy concurrency
Alec Matusis ha scritto:
Here is one tip:
If you have a dual Xeon 5140 (4 cores) machine and run 4 twisted epoll servers in a similar (but not exactly similar situation), it chokes at 30000 clients.
The machine is CPU-bound, and the for loop that loops over clients to send your packets is a performance hog. We are now considering using pyrex for that for loop, or rewriting it with C and libevent.
You can also consider nginx, if you want to write a server in C (or in the D language).
It is a web server, but its core is usable as a framework for generic servers (in fact nginx has also a POP3/IMAP4 proxy server).
nginx has many appealing features, like integrated garbage collector, and multi process workers.
Manlio Perillo
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
![](https://secure.gravatar.com/avatar/4e1ae4b836a9cfe3945d8c661b37246b.jpg?s=120&d=mm&r=g)
Alec Matusis ha scritto:
You can also consider nginx, if you want to write a server in C (or in the D language). It is a web server, but its core is usable as a framework for generic servers (in fact nginx has also a POP3/IMAP4 proxy server).
Do you know if anybody has written general-purpose TCP servers using nginx? It would be interesting to look at.
There are only an HTTP server and a "mail" proxy (POP3/IMAP4/SMTP), and they are quite complex, since there is a lot of boilerplate code. As an example, for mail support there is one "CORE" module ("mail"), and POP3, IMAP4 and SMPT are handled using "sub" modules of this core module. Each core module boilerplate code has to setup the parsing of configuration files and the listening sockets. Manlio Perillo
participants (7)
-
Alec Matusis
-
Atilla
-
glyph@divmod.com
-
Jean-Paul Calderone
-
Manlio Perillo
-
Nicola Larosa
-
Tristan Seligmann