#!/usr/bin/env python """Benchmark for stack_context functionality.""" import collections import contextlib import functools import subprocess import sys from tornado import stack_context class Benchmark(object): def enter_exit(self, count): """Measures the overhead of the nested "with" statements when using many contexts. """ if count < 0: return with self.make_context(): self.enter_exit(count - 1) def call_wrapped(self, count): """Wraps and calls a function at each level of stack depth to measure the overhead of the wrapped function. """ # This queue is analogous to IOLoop.add_callback, but lets us # benchmark the stack_context in isolation without system call # overhead. queue = collections.deque() self.call_wrapped_inner(queue, count) while queue: queue.popleft()() def call_wrapped_inner(self, queue, count): if count < 0: return with self.make_context(): queue.append(stack_context.wrap( functools.partial(self.call_wrapped_inner, queue, count - 1))) class StackBenchmark(Benchmark): def make_context(self): return stack_context.StackContext(self.__context) @contextlib.contextmanager def __context(self): yield class ExceptionBenchmark(Benchmark): def make_context(self): return stack_context.ExceptionStackContext(self.__handle_exception) def __handle_exception(self, typ, value, tb): pass def main(): base_cmd = [ sys.executable, '-m', 'timeit', '-s', 'from stack_context_benchmark import StackBenchmark, ExceptionBenchmark'] cmds = [ 'StackBenchmark().enter_exit(50)', 'StackBenchmark().call_wrapped(50)', 'StackBenchmark().enter_exit(500)', 'StackBenchmark().call_wrapped(500)', 'ExceptionBenchmark().enter_exit(50)', 'ExceptionBenchmark().call_wrapped(50)', 'ExceptionBenchmark().enter_exit(500)', 'ExceptionBenchmark().call_wrapped(500)', ] for cmd in cmds: print(cmd) subprocess.check_call(base_cmd + [cmd]) if __name__ == '__main__': main()