[Twisted-Python] Usenix paper on event dispatch mechanisms
Moshe Zadka
m at moshez.org
Mon Sep 17 14:49:09 MDT 2001
On Mon, 17 Sep 2001, Itamar Shtull-Trauring <lists at itamarst.org> wrote:
> Relevance:
> Doing multiple accept() calls instead of one (after a select() call
> tells you a new connection is available) can speed up your application
> considerably under high loads.
Initial benchmarks show that this is a promising avenue. I got speed-ups
between 10% and 50% depending on the load.
Here is the improved Port class:
>---------- snip ------------<
import fcntl
import FCNTL
class Port(abstract.FileDescriptor):
"""I am a TCP server port, listening for connections.
When a connection is accepted, I will call my factory's buildProtocol with
the incoming connection as an argument, according to the specification
described in twisted.protocols.protocol.Factory.
If you wish to change the sort of transport that will be used, my
`transport' attribute will be called with the signature expected for
Server.__init__, so it can be replaced.
"""
transport = Server
sessionno = 0
unixsocket = None
interface = ''
backlog = 5
def __init__(self, port, factory, backlog=5, interface=''):
"""Initialize with a numeric port to listen on.
"""
self.port = port
self.factory = factory
self.backlog = backlog
self.interface = interface
def __repr__(self):
return "<%s on %s>" % (self.factory.__class__, self.port)
def createInternetSocket(self):
"""(internal) create an AF_INET socket.
"""
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
fcntl.fcntl(s.fileno(), FCNTL.F_SETFL, os.O_NONBLOCK)
return s
def __getstate__(self):
"""(internal) get my state for persistence
"""
dct = copy.copy(self.__dict__)
try: del dct['socket']
except: pass
try: del dct['fileno']
except: pass
return dct
def startListening(self):
"""Create and bind my socket, and begin listening on it.
This is called on unserialization, and must be called after creating a
server to begin listening on the specified port.
"""
log.msg("%s starting on %s"%(self.factory.__class__, self.port))
if type(self.port) == types.StringType:
skt = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
skt.bind(self.port)
# Make the socket readable and writable to the world.
mode = os.stat(self.port)[0]
os.chmod(self.port, mode | stat.S_IROTH | stat.S_IWOTH)
self.unixsocket = 1
else:
skt = self.createInternetSocket()
skt.bind( (self.interface, self.port) )
skt.listen(self.backlog)
self.connected = 1
self.socket = skt
self.fileno = self.socket.fileno
self.startReading()
def doRead(self):
"""Called when my socket is ready for reading.
This accepts a connection and callse self.protocol() to handle the
wire-level protocol.
"""
try:
for i in range(40):
try:
skt,addr = self.socket.accept()
except socket.error, e:
if e.args[0] == EWOULDBLOCK:
break
raise
protocol = self.factory.buildProtocol(addr)
s = self.sessionno
self.sessionno = s+1
transport = self.transport(skt, protocol, addr, self, s)
protocol.makeConnection(transport, self)
except:
traceback.print_exc(file=log.logfile)
def doWrite(self):
"""Raises an AssertionError.
"""
assert 0, "doWrite called on a %s" % str(self.__class__)
def loseConnection(self):
""" Stop accepting connections on this port.
This will shut down my socket and call self.connectionLost().
"""
# Since ports can't, by definition, write any data, we can just close
# instantly (no need for the more complex stuff for selectables which
# write)
self.stopReading()
self.connectionLost()
def connectionLost(self):
"""Cleans up my socket.
"""
log.msg('(Port %s Closed)' % self.port)
abstract.FileDescriptor.connectionLost(self)
self.connected = 0
self.socket.close()
if self.unixsocket:
os.unlink(self.port)
del self.socket
del self.fileno
def logPrefix(self):
"""Returns the name of my class, to prefix log entries with.
"""
return str(self.factory.__class__)
>------------ snip ----------------<
--
The Official Moshe Zadka FAQ: http://moshez.geek
The Official Moshe Zadka FAQ For Dummies: http://moshez.org
Read the FAQ
More information about the Twisted-Python
mailing list