# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ See how fast deferreds are. This is mainly useful to compare cdefer.Deferred to defer.Deferred """ from __future__ import print_function from twisted.internet import defer from twisted.python.compat import range from timer import timeit benchmarkFuncs = [] def benchmarkFunc(iter, args=()): """ A decorator for benchmark functions that measure a single iteration count. Registers the function with the given iteration count to the global benchmarkFuncs list """ def decorator(func): benchmarkFuncs.append((func, args, iter)) return func return decorator def benchmarkNFunc(iter, ns): """ A decorator for benchmark functions that measure multiple iteration counts. Registers the function with the given iteration count to the global benchmarkFuncs list. """ def decorator(func): for n in ns: benchmarkFuncs.append((func, (n,), iter)) return func return decorator def instantiate(): """ Only create a deferred """ d = defer.Deferred() instantiate = benchmarkFunc(100000)(instantiate) def instantiateShootCallback(): """ Create a deferred and give it a normal result """ d = defer.Deferred() d.callback(1) instantiateShootCallback = benchmarkFunc(100000)(instantiateShootCallback) def instantiateShootErrback(): """ Create a deferred and give it an exception result. To avoid Unhandled Errors, also register an errback that eats the error """ d = defer.Deferred() try: 1/0 except: d.errback() d.addErrback(lambda x: None) instantiateShootErrback = benchmarkFunc(200)(instantiateShootErrback) ns = [10, 1000, 10000] def instantiateAddCallbacksNoResult(n): """ Creates a deferred and adds a trivial callback/errback/both to it the given number of times. """ d = defer.Deferred() def f(result): return result for i in range(n): d.addCallback(f) d.addErrback(f) d.addBoth(f) d.addCallbacks(f, f) instantiateAddCallbacksNoResult = benchmarkNFunc(20, ns)(instantiateAddCallbacksNoResult) def instantiateAddCallbacksBeforeResult(n): """ Create a deferred and adds a trivial callback/errback/both to it the given number of times, and then shoots a result through all of the callbacks. """ d = defer.Deferred() def f(result): return result for i in range(n): d.addCallback(f) d.addErrback(f) d.addBoth(f) d.addCallbacks(f) d.callback(1) instantiateAddCallbacksBeforeResult = benchmarkNFunc(20, ns)(instantiateAddCallbacksBeforeResult) def instantiateAddCallbacksAfterResult(n): """ Create a deferred, shoots it and then adds a trivial callback/errback/both to it the given number of times. The result is processed through the callbacks as they are added. """ d = defer.Deferred() def f(result): return result d.callback(1) for i in range(n): d.addCallback(f) d.addErrback(f) d.addBoth(f) d.addCallbacks(f) instantiateAddCallbacksAfterResult = benchmarkNFunc(20, ns)(instantiateAddCallbacksAfterResult) def pauseUnpause(n): """ Adds the given number of callbacks/errbacks/both to a deferred while it is paused, and unpauses it, trigerring the processing of the value through the callbacks. """ d = defer.Deferred() def f(result): return result d.callback(1) d.pause() for i in range(n): d.addCallback(f) d.addErrback(f) d.addBoth(f) d.addCallbacks(f) d.unpause() pauseUnpause = benchmarkNFunc(20, ns)(pauseUnpause) def benchmark(): """ Run all of the benchmarks registered in the benchmarkFuncs list """ print(defer.Deferred.__module__) for func, args, iter in benchmarkFuncs: print(func.__name__, args, timeit(func, iter, *args)) if __name__ == '__main__': benchmark()