[medusa] Multithreaded Medusa

Jim Fulton jim@d...
Wed, 04 Oct 2000 11:46:14 -0400


> Itay Zandbank wrote:
> 
> Aside from stalled producers, I also needed to multi-thread Medusa. I have a proxy server, that does some processing on the passing data. This processing is pretty quick. Quick enough to put in the main select thread without slowing things down (the overhead of delegating the job to another thread, even if that thread is already running, is not worth it). The problem is with multi-CPU machines. On a machine with two CPUs, having two threads can have a drastic impact on performance.

You won't get a drastic improvement in performance using Python, since only one thread
can be in the interpreter at a time. There are exotic ways to get around this involving
running two interpreters, but I haven't tried them.

> What I came up with, then, was this: Have one thread listening for incoming connections, and one (or more, depending on the number of CPUs you have) process these connections. The theory seemed easy enough. But then reality hit me. Since I have two (or more) threads working on network connections, I need two select loops, and more importantly, two socket_maps.
> 
> All throughout Medusa, there's code that assumes the socket map is asyncore.socket_map (in http_server, for instance). What I had to do eventually, was create a class (I called it Redirector), which has two methods - add_channel and del_channel, which put the socket in the right socket_map, like this:
> 
> class Redirector:
> def __init__(self, socket_map):
> self.socket_map = socket_map
> 
> def add_channel(self, map=None):
> if map is None:
> map = self.socket_map
> asynccore.dispatcher.add_channel(self, map)
> 
> def del_channel(self, map=None):
> # Very much like add_channel
> 
> 
> Each time I have an asyncore.dispatcher derived class in my souce, I also derive it from Redirector.
> 
> This works, but it's really ugly (I'm sure that in a month, I'll spend an entire week tracking down a bug caused by not deriving a class from Redirector). It would have been much better if asyncore.dispatcher had a socket_map member in the first place. The default can still be the global socket_map, so no code will break.

I raised this same issue a while ago. At least asyncore now lets
you specify alternate socket maps. :)

Jim


--
Jim Fulton mailto:jim@d... Python Powered! 
Technical Director (888) 344-4332 http://www.python.org 
Digital Creations http://www.digicool.com http://www.zope.org 

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission. Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.