summaryrefslogtreecommitdiff
path: root/benchmarks
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2020-03-11 12:19:19 -0500
committerJason Madden <jamadden@gmail.com>2020-03-18 12:27:20 -0500
commit413e716f9fb48338829435c4f243133589eb9fe6 (patch)
treebd00663da33f5b85af67531627f1e39941307fa6 /benchmarks
parent7afd59d869e3391ce27a4a07ad0931eb5e7910a1 (diff)
downloadzope-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.py50
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,