[Checkins] [zopefoundation/zope.interface] 8ce046: Move Interface hashing and comparison to C; 2.5 to...
Jason Madden
noreply at github.com
Tue Mar 17 11:34:43 CET 2020
Branch: refs/heads/faster-eq-hash-comparison
Home: https://github.com/zopefoundation/zope.interface
Commit: 8ce04640b82eaf327c48b565d3c9f134dcff8d0e
https://github.com/zopefoundation/zope.interface/commit/8ce04640b82eaf327c48b565d3c9f134dcff8d0e
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M MANIFEST.in
A benchmarks/micro.py
M src/zope/interface/_zope_interface_coptimizations.c
M src/zope/interface/interface.py
M src/zope/interface/tests/test_interface.py
M src/zope/interface/tests/test_sorting.py
Log Message:
-----------
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).
Commit: b74595789affbf3d42a0e9c77442004a1c1c146d
https://github.com/zopefoundation/zope.interface/commit/b74595789affbf3d42a0e9c77442004a1c1c146d
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M src/zope/interface/interface.py
Log Message:
-----------
Fix doctest by making sure the default type repr can be used.
Commit: abc51b17a278db1e6ef7e7ad5ab4621818b75960
https://github.com/zopefoundation/zope.interface/commit/abc51b17a278db1e6ef7e7ad5ab4621818b75960
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M benchmarks/micro.py
Log Message:
-----------
Benchmarks looking up adapters from components.
Current results (this branch vs master, 354faccebd5b612a2ac8e081a7e5d2f7fb1089c1):
| Benchmark | 38-master | 38-faster |
|-------------------------------------------|-----------|-------------------------------|
| query adapter (no registrations) | 3.81 ms | 3.03 ms: 1.26x faster (-20%) |
| query adapter (all trivial registrations) | 4.65 ms | 3.90 ms: 1.19x faster (-16%) |
| contains (empty dict) | 163 ns | 76.1 ns: 2.14x faster (-53%) |
| contains (populated dict) | 162 ns | 76.9 ns: 2.11x faster (-53%) |
| contains (populated list) | 40.3 us | 3.09 us: 13.04x faster (-92%) |
Also need benchmarks using inheritance. The 'implied' data structures
are also hash/equality based.
Commit: 7a67b9b58538ea414c39e26c663146132dbb88dd
https://github.com/zopefoundation/zope.interface/commit/7a67b9b58538ea414c39e26c663146132dbb88dd
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M src/zope/interface/tests/test_interface.py
Log Message:
-----------
Clean up linter errors in test_interface.py so new/real problems are more obvious.
Commit: f01e54d3fa0f864b657ec9b0e4782cf6fd1d2317
https://github.com/zopefoundation/zope.interface/commit/f01e54d3fa0f864b657ec9b0e4782cf6fd1d2317
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M src/zope/interface/tests/__init__.py
M src/zope/interface/tests/test_interface.py
Log Message:
-----------
Fix tests when zope.component is also importable.
Commit: 3e54855d417f1ea0553770c93a7ebe4ba670ddf2
https://github.com/zopefoundation/zope.interface/commit/3e54855d417f1ea0553770c93a7ebe4ba670ddf2
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M benchmarks/micro.py
M src/zope/interface/_zope_interface_coptimizations.c
M src/zope/interface/declarations.py
M src/zope/interface/interface.py
M src/zope/interface/tests/test_interface.py
Log Message:
-----------
Avoid use of a metaclass by implementeng __getattribute__.
This is pretty, but it slows down all attribute access to interfaces.
By up to 25%. I'm not sure that's acceptable for things like
Interface.providedBy.
+-------------------------------------------+------------+-------------------------------+
| Benchmark | 38-master3 | 38-faster3 |
+===========================================+============+===============================+
| read __module__ | 41.1 ns | 44.3 ns: 1.08x slower (+8%) |
+-------------------------------------------+------------+-------------------------------+
| read __name__ | 41.3 ns | 51.6 ns: 1.25x slower (+25%) |
+-------------------------------------------+------------+-------------------------------+
| read __doc__ | 41.8 ns | 53.3 ns: 1.28x slower (+28%) |
+-------------------------------------------+------------+-------------------------------+
| read providedBy | 56.7 ns | 71.6 ns: 1.26x slower (+26%) |
+-------------------------------------------+------------+-------------------------------+
| query adapter (no registrations) | 3.85 ms | 2.95 ms: 1.31x faster (-23%) |
+-------------------------------------------+------------+-------------------------------+
| query adapter (all trivial registrations) | 4.59 ms | 3.65 ms: 1.26x faster (-20%) |
+-------------------------------------------+------------+-------------------------------+
| contains (empty dict) | 136 ns | 55.4 ns: 2.45x faster (-59%) |
+-------------------------------------------+------------+-------------------------------+
| contains (populated dict) | 137 ns | 55.0 ns: 2.49x faster (-60%) |
+-------------------------------------------+------------+-------------------------------+
| contains (populated list) | 40.2 us | 2.95 us: 13.62x faster (-93%) |
+-------------------------------------------+------------+-------------------------------+
Commit: 5162b8deb4da7a22115040732f50b3ea84821fbe
https://github.com/zopefoundation/zope.interface/commit/5162b8deb4da7a22115040732f50b3ea84821fbe
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M src/zope/interface/_compat.py
M src/zope/interface/_zope_interface_coptimizations.c
M src/zope/interface/interface.py
M src/zope/interface/tests/test_registry.py
Log Message:
-----------
Use a descriptor for __module__
This makes the rest of the attribute access fast again, but slows down
__module__.
+-------------------------------------------+------------+-------------------------------+
| Benchmark | 38-master3 | 38-faster-descr |
+===========================================+============+===============================+
| read __module__ | 41.1 ns | 123 ns: 2.99x slower (+199%) |
+-------------------------------------------+------------+-------------------------------+
| read __name__ | 41.3 ns | 39.9 ns: 1.04x faster (-3%) |
+-------------------------------------------+------------+-------------------------------+
| read __doc__ | 41.8 ns | 42.4 ns: 1.01x slower (+1%) |
+-------------------------------------------+------------+-------------------------------+
| query adapter (no registrations) | 3.85 ms | 2.95 ms: 1.30x faster (-23%) |
+-------------------------------------------+------------+-------------------------------+
| query adapter (all trivial registrations) | 4.59 ms | 3.67 ms: 1.25x faster (-20%) |
+-------------------------------------------+------------+-------------------------------+
| contains (empty dict) | 136 ns | 54.8 ns: 2.48x faster (-60%) |
+-------------------------------------------+------------+-------------------------------+
| contains (populated dict) | 137 ns | 55.7 ns: 2.46x faster (-59%) |
+-------------------------------------------+------------+-------------------------------+
| contains (populated list) | 40.2 us | 2.86 us: 14.03x faster (-93%) |
+-------------------------------------------+------------+-------------------------------+
Not significant (1): read providedBy
Commit: f1a6da8734bc3737ae2a738ec1e71e4b6856211b
https://github.com/zopefoundation/zope.interface/commit/f1a6da8734bc3737ae2a738ec1e71e4b6856211b
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M benchmarks/micro.py
M src/zope/interface/interface.py
Log Message:
-----------
Move to a metaclass for handling __module__.
This offers the absolute best performance at what seems like reasonable complexity.
+-------------------------------------------------------------+----------------+-------------------------------+
| Benchmark | 38-master-full | 38-faster-meta |
+=============================================================+================+===============================+
| read __module__ | 41.8 ns | 40.9 ns: 1.02x faster (-2%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| read __name__ | 41.8 ns | 39.9 ns: 1.05x faster (-5%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| read providedBy | 56.9 ns | 58.4 ns: 1.03x slower (+3%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| query adapter (no registrations) | 3.85 ms | 2.95 ms: 1.31x faster (-24%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| query adapter (all trivial registrations) | 4.62 ms | 3.63 ms: 1.27x faster (-21%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| query adapter (all trivial registrations, wide inheritance) | 51.8 us | 42.2 us: 1.23x faster (-19%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| query adapter (all trivial registrations, deep inheritance) | 52.0 us | 41.7 us: 1.25x faster (-20%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| sort interfaces | 234 us | 29.9 us: 7.84x faster (-87%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| sort mixed | 569 us | 340 us: 1.67x faster (-40%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| contains (empty dict) | 135 ns | 55.2 ns: 2.44x faster (-59%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| contains (populated dict: interfaces) | 137 ns | 56.1 ns: 2.45x faster (-59%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| contains (populated list: interfaces) | 39.7 us | 2.96 us: 13.42x faster (-93%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| contains (populated dict: implementedBy) | 137 ns | 55.2 ns: 2.48x faster (-60%) |
+-------------------------------------------------------------+----------------+-------------------------------+
| contains (populated list: implementedBy) | 40.6 us | 24.1 us: 1.68x faster (-41%) |
+-------------------------------------------------------------+----------------+-------------------------------+
Not significant (2): read __doc__; sort implementedBy
Commit: 6984592e8fe0f6e1ebf602177a98114128169f60
https://github.com/zopefoundation/zope.interface/commit/6984592e8fe0f6e1ebf602177a98114128169f60
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M src/zope/interface/_zope_interface_coptimizations.c
Log Message:
-----------
Several small tweaks to GC and deletion handling.
Several places needed to, essentially, call super.
Commit: 0575913147849f6e614afdbdf5c90315e5efa973
https://github.com/zopefoundation/zope.interface/commit/0575913147849f6e614afdbdf5c90315e5efa973
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M CHANGES.rst
M src/zope/interface/_zope_interface_coptimizations.c
M src/zope/interface/interface.py
M src/zope/interface/tests/test_declarations.py
M src/zope/interface/tests/test_interface.py
Log Message:
-----------
Add tests for comparing InterfaceClass/Implements objects to things without the required attributes.
And fix the C handling of this case.
Commit: 573c7f0d352da96edb79f459ce37cda8cd10f9a6
https://github.com/zopefoundation/zope.interface/commit/573c7f0d352da96edb79f459ce37cda8cd10f9a6
Author: Jason Madden <jamadden at gmail.com>
Date: 2020-03-17 (Tue, 17 Mar 2020)
Changed paths:
M src/zope/interface/tests/test_interface.py
Log Message:
-----------
Add additional tests for assigning to Interface.__module__.
Compare: https://github.com/zopefoundation/zope.interface/compare/f5299f1043f1...573c7f0d352d
More information about the checkins
mailing list