-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move Interface hashing and comparison to C; 2.5 to 15x speedup in mic…
…ro 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).
- Loading branch information
Showing
6 changed files
with
361 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,3 +18,4 @@ global-exclude coverage.xml | |
global-exclude appveyor.yml | ||
|
||
prune docs/_build | ||
prune benchmarks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.