From 9ec920e99aa8a31cbe5ef7140573551e5c4f63ff Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sun, 17 Nov 2024 08:42:20 +0100 Subject: [PATCH] Add benchmark for routing sub_applications (#9935) Router should be optimized for handling 2 kind of prefix resources (sub_apps and static files are handled equally now): 1. sub_apps are placed under non-overlapped top-level single-segment prefixed. `test_resolve_gitapi_subapps` benchmark test this case already. 2. sub_apps shares the same prefix segments, e.g. `/api/manager/plugin/{name}`. This PR covers the second case. (cherry picked from commit 0c312496c6490f934cec360f21ae802e2c8d8679) --- tests/test_benchmarks_web_urldispatcher.py | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/test_benchmarks_web_urldispatcher.py b/tests/test_benchmarks_web_urldispatcher.py index 16a59516b35..662a600c3b3 100644 --- a/tests/test_benchmarks_web_urldispatcher.py +++ b/tests/test_benchmarks_web_urldispatcher.py @@ -377,3 +377,37 @@ async def run_url_dispatcher_benchmark() -> None: @benchmark def _run() -> None: loop.run_until_complete(run_url_dispatcher_benchmark()) + + +def test_resolve_prefix_resources_many_prefix_many_plain( + loop: asyncio.AbstractEventLoop, + benchmark: BenchmarkFixture, +) -> None: + """Resolve prefix resource (sub_app) whene 250 PlainResources registered and there are 250 subapps that shares the same sub_app path prefix.""" + + async def handler(request: web.Request) -> NoReturn: + assert False + + app = web.Application() + for count in range(250): + app.router.add_get(f"/api/server/other/{count}/update", handler) + for count in range(250): + subapp = web.Application() + # sub_apps exists for handling deep enough nested route trees + subapp.router.add_get("/deep/enough/sub/path", handler) + app.add_subapp(f"/api/path/to/plugin/{count}", subapp) + app.freeze() + router = app.router + + requests = [ + _mock_request(method="GET", path="/api/path/to/plugin/249/deep/enough/sub/path") + for customer in range(250) + ] + + async def run_url_dispatcher_benchmark() -> None: + for request in requests: + await router.resolve(request) + + @benchmark + def _run() -> None: + loop.run_until_complete(run_url_dispatcher_benchmark())