[pypy-svn] r71810 - in pypy/benchmarks: . own own/twisted unladen_swallow

fijal at codespeak.net fijal at codespeak.net
Fri Mar 5 17:20:24 CET 2010


Author: fijal
Date: Fri Mar  5 17:20:22 2010
New Revision: 71810

Added:
   pypy/benchmarks/own/twisted/
   pypy/benchmarks/own/twisted/TODO
   pypy/benchmarks/own/twisted/accepts.py   (contents, props changed)
   pypy/benchmarks/own/twisted/all.py   (contents, props changed)
   pypy/benchmarks/own/twisted/benchlib.py   (contents, props changed)
   pypy/benchmarks/own/twisted/iteration.py   (contents, props changed)
   pypy/benchmarks/own/twisted/names.py   (contents, props changed)
   pypy/benchmarks/own/twisted/pb.py   (contents, props changed)
   pypy/benchmarks/own/twisted/tcp.py   (contents, props changed)
   pypy/benchmarks/own/twisted/threads.py   (contents, props changed)
   pypy/benchmarks/own/twisted/web.py   (contents, props changed)
Removed:
   pypy/benchmarks/own/twisted_benchlib.py
   pypy/benchmarks/own/twisted_iteration.py
   pypy/benchmarks/own/twisted_names.py
   pypy/benchmarks/own/twisted_web.py
Modified:
   pypy/benchmarks/benchmarks.py
   pypy/benchmarks/unladen_swallow/perf.py
Log:
Import twisted benchmarks from their official place. Kill our edited versions.

By default we run 3 iterations of warmup + 10 iterations of normal, until
we have a better metric, that's probably fine


Modified: pypy/benchmarks/benchmarks.py
==============================================================================
--- pypy/benchmarks/benchmarks.py	(original)
+++ pypy/benchmarks/benchmarks.py	Fri Mar  5 17:20:22 2010
@@ -17,22 +17,34 @@
 
     d[BM.func_name] = BM
 
-TWISTED = [relative('lib/twisted-trunk'), relative('lib/zope.interface-3.5.3/src')]
+def _register_new_bm_twisted(name, bm_name, d, **opts):
+    def Measure(python, options):
+        def parser(line):
+            number = float(line.split(" ")[0])
+            return 3000/number
+        bm_path = relative('own', 'twisted', name + '.py')
+        return MeasureGeneric(python, options, bm_path, parser=parser, **opts)
+    Measure.func_name = 'Measure' + name.capitalize()
+
+    def BM(*args, **kwds):
+        return SimpleBenchmark(Measure, *args, **kwds)
+    BM.func_name = 'BM_' + bm_name
+
+    d[BM.func_name] = BM
+
+TWISTED = [relative('lib/twisted-trunk'), relative('lib/zope.interface-3.5.3/src'), relative('own/twisted')]
 
 opts = {
     'gcbench' : {'iteration_scaling' : .10},
-    'twisted_iteration': {'iteration_scaling': .10,
-        'bm_env': {'PYTHONPATH': ':'.join(TWISTED)}},
-    'twisted_web': {'iteration_scaling': .10,
-        'bm_env': {'PYTHONPATH': ':'.join(TWISTED)}},
-    'twisted_names': {'iteration_scaling': .10,
-        'bm_env': {'PYTHONPATH': ':'.join(TWISTED)}},
 }
 
 for name in ['float', 'nbody_modified', 'meteor-contest', 'fannkuch',
-             'spectral-norm', 'chaos', 'telco', 'gcbench',
-             'twisted_iteration', 'twisted_web', 'twisted_names']:
+             'spectral-norm', 'chaos', 'telco']:
     _register_new_bm(name, name, globals(), **opts.get(name, {}))
+for name in ['web', 'names', 'accepts', 'iteration', 'tcp', 'pb']:
+    _register_new_bm_twisted(name, 'twisted_' + name,
+                     globals(), bm_env={'PYTHONPATH': ':'.join(TWISTED)},
+                                 iteration_scaling=.20)
 _register_new_bm('spitfire', 'spitfire', globals(),
     extra_args=['--benchmark=spitfire_o4'])
 _register_new_bm('spitfire', 'spitfire_cstringio', globals(),

Added: pypy/benchmarks/own/twisted/TODO
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/TODO	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,2 @@
+Debug dns slowdown over time
+Add an AMP benchmark

Added: pypy/benchmarks/own/twisted/accepts.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/accepts.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,55 @@
+
+from __future__ import division
+
+from twisted.internet.protocol import ServerFactory, ClientFactory, Protocol
+from twisted.internet.error import ConnectionClosed
+from twisted.internet.defer import Deferred
+
+from benchlib import Client, driver
+
+
+class Client(Client):
+    def __init__(self, reactor, portNumber):
+        super(Client, self).__init__(reactor)
+        self._portNumber = portNumber
+        self._factory = ClientFactory()
+
+
+    def _request(self):
+        finished = Deferred()
+        factory = ClientFactory()
+        factory.protocol = Protocol
+        factory.clientConnectionLost = factory.clientConnectionFailed = lambda connector, reason: finished.errback(reason)
+        finished.addErrback(self._filterFinished)
+        self._reactor.connectTCP('127.0.0.1', self._portNumber, factory)
+        finished.addCallback(self._continue)
+        finished.addErrback(self._stop)
+
+
+    def _filterFinished(self, reason):
+        reason.trap(ConnectionClosed)
+
+
+class CloseConnection(Protocol):
+    def makeConnection(self, transport):
+        transport.loseConnection()
+
+
+
+def main(reactor, duration):
+    concurrency = 50
+
+    factory = ServerFactory()
+    factory.protocol = CloseConnection
+    port = reactor.listenTCP(0, factory)
+
+    client = Client(reactor, port.getHost().port)
+    d = client.run(concurrency, duration)
+    return d
+
+
+
+if __name__ == '__main__':
+    import sys
+    import accepts
+    driver(accepts.main, sys.argv)

Added: pypy/benchmarks/own/twisted/all.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/all.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,8 @@
+
+from benchlib import multidriver
+
+import accepts, tcp, iteration, names, threads, web, pb
+
+if __name__ == '__main__':
+    multidriver(
+        accepts.main, tcp.main, iteration.main, names.main, threads.main, web.main, pb.main)

Added: pypy/benchmarks/own/twisted/benchlib.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/benchlib.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,87 @@
+
+import sys
+from twisted.internet.defer import Deferred
+from twisted.internet import reactor
+from twisted.python import log
+
+class Client(object):
+    def __init__(self, reactor):
+        self._reactor = reactor
+        self._requestCount = 0
+
+    def run(self, concurrency, duration):
+        self._reactor.callLater(duration, self._stop, None)
+        self._finished = Deferred()
+        for i in range(concurrency):
+            self._request()
+        return self._finished
+
+    def _continue(self, ignored):
+        self._requestCount += 1
+        if self._finished is not None:
+            self._request()
+
+    def _stop(self, reason):
+        if self._finished is not None:
+            finished = self._finished
+            self._finished = None
+            if reason is not None:
+                finished.errback(reason)
+            else:
+                finished.callback(self._requestCount)
+
+PRINT_TEMPL = ('%(stats)s %(name)s/sec (%(count)s %(name)s '
+              'in %(duration)s seconds)')
+
+def benchmark_report(acceptCount, duration, name):
+    print PRINT_TEMPL % {
+        'stats'    : acceptCount / duration,
+        'name'     : name,
+        'count'    : acceptCount,
+        'duration' : duration
+        }
+
+def setup_driver(f, argv, reactor):
+    from twisted.python.usage import Options
+
+    class BenchmarkOptions(Options):
+        optParameters = [
+            ('iterations', 'n', 1, 'number of iterations', int),
+            ('duration', 'd', 5, 'duration of each iteration', float),
+            ('warmup', 'w', 3, 'number of warmup iterations', int),
+        ]
+
+    options = BenchmarkOptions()
+    options.parseOptions(argv[1:])
+    duration = options['duration']
+    jobs = [f] * options['iterations']
+    d = Deferred()
+    def work(res, counter):
+        try:
+            f = jobs.pop()
+        except IndexError:
+            d.callback(None)
+        else:
+            next = f(reactor, duration)
+            if counter <= 0:
+                next.addCallback(benchmark_report, duration, f.__module__)
+            next.addCallbacks(work, d.errback, (counter - 1,))
+    work(None, options['warmup'])
+    return d
+
+def driver(f, argv):
+    d = setup_driver(f, argv, reactor)
+    d.addErrback(log.err)
+    reactor.callWhenRunning(d.addBoth, lambda ign: reactor.stop())
+    reactor.run()
+
+def multidriver(*f):
+    jobs = iter(f)
+    def work():
+        for job in jobs:
+            d = setup_driver(job, sys.argv, reactor)
+            d.addCallback(lambda ignored: work())
+            return
+        reactor.stop()
+    reactor.callWhenRunning(work)
+    reactor.run()

Added: pypy/benchmarks/own/twisted/iteration.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/iteration.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,25 @@
+
+from __future__ import division
+
+from benchlib import Client, driver
+
+
+class Client(Client):
+    def _request(self):
+        self._reactor.callLater(0.0, self._continue, None)
+
+
+
+def main(reactor, duration):
+    concurrency = 10
+
+    client = Client(reactor)
+    d = client.run(concurrency, duration)
+    return d
+
+
+
+if __name__ == '__main__':
+    import sys
+    import iteration
+    driver(iteration.main, sys.argv)

Added: pypy/benchmarks/own/twisted/names.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/names.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,47 @@
+
+from __future__ import division
+
+from twisted.names.dns import DNSDatagramProtocol
+from twisted.names.server import DNSServerFactory
+from twisted.names import hosts, client
+
+from benchlib import Client, driver
+
+
+class Client(Client):
+    def __init__(self, reactor, portNumber, timeout):
+        self._resolver = client.Resolver(servers=[('127.0.0.1', portNumber)])
+        self._timeout = timeout
+        super(Client, self).__init__(reactor)
+
+
+    def _request(self):
+        d = self._resolver.lookupAddress(
+            'localhost', timeout=(self._timeout,))
+        d.addCallback(self._continue)
+        d.addErrback(self._stop)
+
+
+
+
+def main(reactor, duration):
+    concurrency = 10
+
+    controller = DNSServerFactory([hosts.Resolver()])
+    port = reactor.listenUDP(0, DNSDatagramProtocol(controller))
+    # Have queries time out no sooner than the duration of this benchmark so
+    # we don't have to deal with retries or timeout errors.
+    client = Client(reactor, port.getHost().port, duration)
+    d = client.run(concurrency, duration)
+    def cleanup(passthrough):
+        d = port.stopListening()
+        d.addCallback(lambda ign: passthrough)
+        return d
+    d.addBoth(cleanup)
+    return d
+
+
+if __name__ == '__main__':
+    import sys
+    import names
+    driver(names.main, sys.argv)

Added: pypy/benchmarks/own/twisted/pb.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/pb.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,61 @@
+
+"""
+Benchmark for Twisted Spread.
+"""
+
+from __future__ import division
+
+from twisted.spread.pb import PBServerFactory, PBClientFactory, Root
+
+from benchlib import Client, driver
+
+
+class BenchRoot(Root):
+    def remote_discard(self, argument):
+        pass
+
+
+
+class Client(Client):
+    _structure = [
+        'hello' * 100,
+        {'foo': 'bar',
+         'baz': 100,
+         u'these are bytes': (1, 2, 3)}]
+
+    def __init__(self, reactor, port):
+        super(Client, self).__init__(reactor)
+        self._port = port
+
+
+    def run(self, *args, **kwargs):
+        def connected(reference):
+            self._reference = reference
+            return super(Client, self).run(*args, **kwargs)
+        client = PBClientFactory()
+        d = client.getRootObject()
+        d.addCallback(connected)
+        self._reactor.connectTCP('127.0.0.1', self._port, client)
+        return d
+
+
+    def _request(self):
+        d = self._reference.callRemote('discard', self._structure)
+        d.addCallback(self._continue)
+        d.addErrback(self._stop)
+
+
+def main(reactor, duration):
+    concurrency = 15
+
+    server = PBServerFactory(BenchRoot())
+    port = reactor.listenTCP(0, server)
+    client = Client(reactor, port.getHost().port)
+    d = client.run(concurrency, duration)
+    return d
+
+
+if __name__ == '__main__':
+    import sys
+    import pb
+    driver(pb.main, sys.argv)

Added: pypy/benchmarks/own/twisted/tcp.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/tcp.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,93 @@
+
+"""
+This benchmarks runs a trivial Twisted TCP echo server and a client pumps as
+much data to it as it can in a fixed period of time.
+
+The size of the string passed to each write call may play a significant
+factor in the performance of this benchmark.
+"""
+
+from __future__ import division
+
+from twisted.internet.defer import Deferred
+from twisted.internet.protocol import ServerFactory, ClientCreator, Protocol
+from twisted.protocols.wire import Echo
+
+from benchlib import driver
+
+
+class Counter(Protocol):
+    count = 0
+
+    def dataReceived(self, bytes):
+        self.count += len(bytes)
+
+
+
+class Client(object):
+    _finished = None
+
+    def __init__(self, reactor, port):
+        self._reactor = reactor
+        self._port = port
+
+
+    def run(self, duration, chunkSize):
+        self._duration = duration
+        self._bytes = 'x' * chunkSize
+        # Set up a connection
+        cc = ClientCreator(self._reactor, Counter)
+        d = cc.connectTCP('127.0.0.1', self._port)
+        d.addCallback(self._connected)
+        return d
+
+
+    def _connected(self, client):
+        self._client = client
+        self._stopCall = self._reactor.callLater(self._duration, self._stop)
+        client.transport.registerProducer(self, False)
+        self._finished = Deferred()
+        return self._finished
+
+
+    def _stop(self):
+        self.stopProducing()
+        self._client.transport.unregisterProducer()
+        self._finish(self._client.count)
+
+
+    def _finish(self, value):
+        if self._finished is not None:
+            finished = self._finished
+            self._finished = None
+            finished.callback(value)
+
+
+    def resumeProducing(self):
+        self._client.transport.write(self._bytes)
+
+
+    def stopProducing(self):
+        self._client.transport.loseConnection()
+
+
+    def connectionLost(self, reason):
+        self._finish(reason)
+
+
+ 
+def main(reactor, duration):
+    chunkSize = 16384
+
+    server = ServerFactory()
+    server.protocol = Echo
+    serverPort = reactor.listenTCP(0, server)
+    client = Client(reactor, serverPort.getHost().port)
+    d = client.run(duration, chunkSize)
+    return d
+
+
+if __name__ == '__main__':
+    import sys
+    import tcp
+    driver(tcp.main, sys.argv)

Added: pypy/benchmarks/own/twisted/threads.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/threads.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,29 @@
+
+from __future__ import division
+
+from twisted.internet.threads import deferToThread
+
+from benchlib import Client, driver
+
+
+class Client(Client):
+    def _request(self):
+        d = deferToThread(lambda: None)
+        d.addCallback(self._continue)
+        d.addErrback(self._stop)
+
+
+
+def main(reactor, duration):
+    concurrency = 10
+
+    client = Client(reactor)
+    d = client.run(concurrency, duration)
+    return d
+
+
+
+if __name__ == '__main__':
+    import sys
+    import threads
+    driver(threads.main, sys.argv)

Added: pypy/benchmarks/own/twisted/web.py
==============================================================================
--- (empty file)
+++ pypy/benchmarks/own/twisted/web.py	Fri Mar  5 17:20:22 2010
@@ -0,0 +1,76 @@
+
+"""
+This benchmark runs a trivial Twisted Web server and client and makes as
+many requests as it can in a fixed period of time.
+
+A significant problem with this benchmark is the lack of persistent
+connections in the HTTP client.  Lots of TCP connections means lots of
+overhead in the kernel that's not really what we're trying to benchmark. 
+Plus lots of sockets end up in TIME_WAIT which has a (briefly) persistent
+effect on system-wide performance and makes consecutive runs of the
+benchmark vary wildly in their results.
+"""
+
+from __future__ import division
+
+from twisted.internet.protocol import Protocol
+from twisted.internet.defer import Deferred
+from twisted.web.server import Site
+from twisted.web.static import Data
+from twisted.web.resource import Resource
+from twisted.web.client import ResponseDone, Agent
+
+from benchlib import Client, driver
+
+
+class BodyConsumer(Protocol):
+    def __init__(self, finished):
+        self.finished = finished
+
+    def connectionLost(self, reason):
+        if reason.check(ResponseDone):
+            self.finished.callback(None)
+        else:
+            self.finished.errback(reason)
+
+
+
+class Client(Client):
+    def __init__(self, reactor, portNumber, agent):
+        self._requestLocation = 'http://127.0.0.1:%d/' % (portNumber,)
+        self._agent = agent
+        super(Client, self).__init__(reactor)
+
+
+    def _request(self):
+        d = self._agent.request('GET', self._requestLocation)
+        d.addCallback(self._read)
+        d.addCallback(self._continue)
+        d.addErrback(self._stop)
+
+
+    def _read(self, response):
+        finished = Deferred()
+        response.deliverBody(BodyConsumer(finished))
+        return finished
+
+
+
+def main(reactor, duration):
+    concurrency = 10
+
+    root = Resource()
+    root.putChild('', Data("Hello, world", "text/plain"))
+    port = reactor.listenTCP(
+        0, Site(root), backlog=128, interface='127.0.0.1')
+    agent = Agent(reactor)
+    client = Client(reactor, port.getHost().port, agent)
+    d = client.run(concurrency, duration)
+    return d
+
+
+
+if __name__ == '__main__':
+    import sys
+    import web
+    driver(web.main, sys.argv)

Modified: pypy/benchmarks/unladen_swallow/perf.py
==============================================================================
--- pypy/benchmarks/unladen_swallow/perf.py	(original)
+++ pypy/benchmarks/unladen_swallow/perf.py	Fri Mar  5 17:20:22 2010
@@ -754,7 +754,7 @@
 
 
 def MeasureGeneric(python, options, bm_path, bm_env=None,
-                   extra_args=[], iteration_scaling=1):
+                   extra_args=[], iteration_scaling=1, parser=float):
     """Abstract measurement function for Unladen's bm_* scripts.
 
     Based on the values of options.fast/rigorous, will pass -n {5,50,100} to
@@ -792,7 +792,7 @@
     result, mem_usage = CallAndCaptureOutput(command, bm_env,
                                              track_memory=options.track_memory,
                                              inherit_env=options.inherit_env)
-    times = [float(line) for line in result.splitlines()]
+    times = [parser(line) for line in result.splitlines()]
     return times, mem_usage
 
 



More information about the Pypy-commit mailing list