diff options
| author | Jason Madden <jamadden@gmail.com> | 2020-03-06 18:38:50 -0600 |
|---|---|---|
| committer | Jason Madden <jamadden@gmail.com> | 2020-03-18 12:26:35 -0500 |
| commit | 8ac3bd088d9b924cfb3170b77b41effd2de39d23 (patch) | |
| tree | 42c4c9f92b09dab763c0ecd0a9a916a7f24caad7 /benchmarks | |
| parent | 13de77d4edfc64c89533656220030230bcf2d895 (diff) | |
| download | zope-interface-8ac3bd088d9b924cfb3170b77b41effd2de39d23.tar.gz | |
Move Interface hashing and comparison to C; 2.5 to 15x speedup in micro benchmarks
Included benchmark numbers:
Current master, Python 3.8:
.....................
contains (empty dict): Mean +- std dev: 198 ns +- 5 ns
.....................
contains (populated dict): Mean +- std dev: 197 ns +- 6 ns
.....................
contains (populated list): Mean +- std dev: 53.1 us +- 1.2 us
This code:
.....................
contains (empty dict): Mean +- std dev: 77.9 ns +- 2.3 ns
.....................
contains (populated dict): Mean +- std dev: 78.4 ns +- 3.1 ns
.....................
contains (populated list): Mean +- std dev: 3.69 us +- 0.08 us
So anywhere from 2.5 to 15x faster. Not sure how that will translate to
larger benchmarks, but I'm hopeful.
It turns out that messing with ``__module__`` is nasty, tricky
business, especially when you do it from C. Everytime you define a new
subclass, the descriptors that you set get overridden by the type
machinery (PyType_Ready). I'm using a data descriptor and a meta class
right now to avoid that but I'm not super happy with that and would
like to find a better way. (At least, maybe the data part of the
descriptor isn't necessary?) It may be needed to move more code into
C, I don't want a slowdown accessing ``__module__`` either; copying
around the standard PyGetSet or PyMember descriptors isn't enough
because they don't work on the class object (so
``classImplements(InterfaceClass, IInterface)`` fails).
Diffstat (limited to 'benchmarks')
| -rw-r--r-- | benchmarks/micro.py | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/benchmarks/micro.py b/benchmarks/micro.py new file mode 100644 index 0000000..0494b56 --- /dev/null +++ b/benchmarks/micro.py @@ -0,0 +1,42 @@ +import pyperf + +from zope.interface import Interface +from zope.interface.interface import InterfaceClass + +ifaces = [ + InterfaceClass('I' + str(i), (Interface,), {}) + for i in range(100) +] + +INNER = 1000 + +def bench_in(loops, o): + t0 = pyperf.perf_counter() + for _ in range(loops): + for _ in range(INNER): + o.__contains__(Interface) + + return pyperf.perf_counter() - t0 + +runner = pyperf.Runner() + +runner.bench_time_func( + 'contains (empty dict)', + bench_in, + {}, + inner_loops=INNER +) + +runner.bench_time_func( + 'contains (populated dict)', + bench_in, + {k: k for k in ifaces}, + inner_loops=INNER +) + +runner.bench_time_func( + 'contains (populated list)', + bench_in, + ifaces, + inner_loops=INNER +) |
