diff --git a/setup.cfg b/setup.cfg index 2b55722e..7040bcb8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -46,6 +46,7 @@ dev = tox testing = pytest + pytest-benchmark [devpi:upload] formats=sdist.tgz,bdist_wheel diff --git a/testing/benchmark.py b/testing/benchmark.py index e0d8b031..b0d4b953 100644 --- a/testing/benchmark.py +++ b/testing/benchmark.py @@ -2,7 +2,7 @@ Benchmarking and performance tests. """ import pytest -from pluggy import HookspecMarker, HookimplMarker +from pluggy import HookspecMarker, HookimplMarker, PluginManager from pluggy._hooks import HookImpl from pluggy._callers import _multicall @@ -43,3 +43,60 @@ def setup(): return (hook_name, hook_impls, caller_kwargs, firstresult), {} benchmark.pedantic(_multicall, setup=setup) + + +@pytest.mark.parametrize( + ("plugins, wrappers, nesting"), + [ + (1, 1, 0), + (1, 1, 1), + (1, 1, 5), + (1, 5, 1), + (1, 5, 5), + (5, 1, 1), + (5, 1, 5), + (5, 5, 1), + (5, 5, 5), + (20, 20, 0), + (100, 100, 0), + ], +) +def test_call_hook(benchmark, plugins, wrappers, nesting): + pm = PluginManager("example") + + class HookSpec: + @hookspec + def fun(self, hooks, nesting: int): + yield + + class Plugin: + def __init__(self, num): + self.num = num + + def __repr__(self): + return f"" + + @hookimpl + def fun(self, hooks, nesting: int): + if nesting: + hooks.fun(hooks=hooks, nesting=nesting - 1) + + class PluginWrap: + def __init__(self, num): + self.num = num + + def __repr__(self): + return f"" + + @hookimpl(hookwrapper=True) + def fun(self): + yield + + pm.add_hookspecs(HookSpec) + + for i in range(plugins): + pm.register(Plugin(i), name=f"plug_{i}") + for i in range(wrappers): + pm.register(PluginWrap(i), name=f"wrap_plug_{i}") + + benchmark(pm.hook.fun, hooks=pm.hook, nesting=nesting)