benchmark.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. """
  2. Benchmarking and performance tests.
  3. """
  4. import pytest
  5. from pluggy import HookimplMarker
  6. from pluggy import HookspecMarker
  7. from pluggy import PluginManager
  8. from pluggy._callers import _multicall
  9. from pluggy._hooks import HookImpl
  10. hookspec = HookspecMarker("example")
  11. hookimpl = HookimplMarker("example")
  12. @hookimpl
  13. def hook(arg1, arg2, arg3):
  14. return arg1, arg2, arg3
  15. @hookimpl(wrapper=True)
  16. def wrapper(arg1, arg2, arg3):
  17. return (yield)
  18. @pytest.fixture(params=[10, 100], ids="hooks={}".format)
  19. def hooks(request):
  20. return [hook for i in range(request.param)]
  21. @pytest.fixture(params=[10, 100], ids="wrappers={}".format)
  22. def wrappers(request):
  23. return [wrapper for i in range(request.param)]
  24. def test_hook_and_wrappers_speed(benchmark, hooks, wrappers):
  25. def setup():
  26. hook_name = "foo"
  27. hook_impls = []
  28. for method in hooks + wrappers:
  29. f = HookImpl(None, "<temp>", method, method.example_impl)
  30. hook_impls.append(f)
  31. caller_kwargs = {"arg1": 1, "arg2": 2, "arg3": 3}
  32. firstresult = False
  33. return (hook_name, hook_impls, caller_kwargs, firstresult), {}
  34. benchmark.pedantic(_multicall, setup=setup, rounds=10)
  35. @pytest.mark.parametrize(
  36. ("plugins, wrappers, nesting"),
  37. [
  38. (1, 1, 0),
  39. (1, 1, 1),
  40. (1, 1, 5),
  41. (1, 5, 1),
  42. (1, 5, 5),
  43. (5, 1, 1),
  44. (5, 1, 5),
  45. (5, 5, 1),
  46. (5, 5, 5),
  47. (20, 20, 0),
  48. (100, 100, 0),
  49. ],
  50. )
  51. def test_call_hook(benchmark, plugins, wrappers, nesting):
  52. pm = PluginManager("example")
  53. class HookSpec:
  54. @hookspec
  55. def fun(self, hooks, nesting: int):
  56. pass
  57. class Plugin:
  58. def __init__(self, num: int) -> None:
  59. self.num = num
  60. def __repr__(self) -> str:
  61. return f"<Plugin {self.num}>"
  62. @hookimpl
  63. def fun(self, hooks, nesting: int) -> None:
  64. if nesting:
  65. hooks.fun(hooks=hooks, nesting=nesting - 1)
  66. class PluginWrap:
  67. def __init__(self, num: int) -> None:
  68. self.num = num
  69. def __repr__(self) -> str:
  70. return f"<PluginWrap {self.num}>"
  71. @hookimpl(wrapper=True)
  72. def fun(self):
  73. return (yield)
  74. pm.add_hookspecs(HookSpec)
  75. for i in range(plugins):
  76. pm.register(Plugin(i), name=f"plug_{i}")
  77. for i in range(wrappers):
  78. pm.register(PluginWrap(i), name=f"wrap_plug_{i}")
  79. benchmark(pm.hook.fun, hooks=pm.hook, nesting=nesting)