diff options
| author | Jason Madden <jamadden@gmail.com> | 2020-03-11 12:19:19 -0500 |
|---|---|---|
| committer | Jason Madden <jamadden@gmail.com> | 2020-03-18 12:27:20 -0500 |
| commit | 413e716f9fb48338829435c4f243133589eb9fe6 (patch) | |
| tree | bd00663da33f5b85af67531627f1e39941307fa6 /benchmarks | |
| parent | 7afd59d869e3391ce27a4a07ad0931eb5e7910a1 (diff) | |
| download | zope-interface-413e716f9fb48338829435c4f243133589eb9fe6.tar.gz | |
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%) |
+-------------------------------------------+------------+-------------------------------+
Diffstat (limited to 'benchmarks')
| -rw-r--r-- | benchmarks/micro.py | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/benchmarks/micro.py b/benchmarks/micro.py index 9031261..779298c 100644 --- a/benchmarks/micro.py +++ b/benchmarks/micro.py @@ -27,7 +27,7 @@ providers = [ for implementer in implementers ] -INNER = 10 +INNER = 100 def bench_in(loops, o): t0 = pyperf.perf_counter() @@ -50,8 +50,56 @@ def bench_query_adapter(loops, components): components.queryAdapter(provider, iface) return pyperf.perf_counter() - t0 +def bench_getattr(loops, name, get=getattr): + t0 = pyperf.perf_counter() + for _ in range(loops): + for _ in range(INNER): + get(Interface, name) # 1 + get(Interface, name) # 2 + get(Interface, name) # 3 + get(Interface, name) # 4 + get(Interface, name) # 5 + get(Interface, name) # 6 + get(Interface, name) # 7 + get(Interface, name) # 8 + get(Interface, name) # 9 + get(Interface, name) # 10 + return pyperf.perf_counter() - t0 + runner = pyperf.Runner() +# TODO: Need benchmarks of adaptation, etc, using interface inheritance. +# TODO: Need benchmarks of sorting (e.g., putting in a BTree) +# TODO: Need those same benchmarks for implementedBy/Implements objects. + +runner.bench_time_func( + 'read __module__', # stored in C, accessed through __getattribute__ + bench_getattr, + '__module__', + inner_loops=INNER * 10 +) + +runner.bench_time_func( + 'read __name__', # stored in C, accessed through PyMemberDef + bench_getattr, + '__name__', + inner_loops=INNER * 10 +) + +runner.bench_time_func( + 'read __doc__', # stored in Python instance dictionary directly + bench_getattr, + '__doc__', + inner_loops=INNER * 10 +) + +runner.bench_time_func( + 'read providedBy', # from the class, wrapped into a method object. + bench_getattr, + 'providedBy', + inner_loops=INNER * 10 +) + runner.bench_time_func( 'query adapter (no registrations)', bench_query_adapter, |
