mirror of
https://github.com/shy3130/tick-stock-panel.git
synced 2026-11-02 10:26:13 +00:00
75 lines
2.4 KiB
Python
75 lines
2.4 KiB
Python
"""Compare per-request HTTP clients with one client per pull using a mock server.
|
|
|
|
Run: uv run --frozen python -m scripts.benchmark_ext_pull_client
|
|
No external network requests or user data are used.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import statistics
|
|
import time
|
|
from datetime import date
|
|
|
|
import httpx
|
|
|
|
from app.services import ext_pull
|
|
from app.services.ext_data import ExtConfig, PullConfig
|
|
|
|
PAGES = 30
|
|
RUNS = 5
|
|
|
|
|
|
async def run(shared: bool) -> tuple[float, int, int]:
|
|
clients = 0
|
|
requests = 0
|
|
real_client = httpx.AsyncClient
|
|
|
|
def respond(request: httpx.Request) -> httpx.Response:
|
|
nonlocal requests
|
|
requests += 1
|
|
page = int(request.url.params["page"])
|
|
return httpx.Response(200, json=[{"symbol": "000001.SZ"}] if page <= PAGES else [])
|
|
|
|
def factory(*args, **kwargs):
|
|
nonlocal clients
|
|
clients += 1
|
|
return real_client(*args, transport=httpx.MockTransport(respond), **kwargs)
|
|
|
|
original = ext_pull.httpx.AsyncClient
|
|
ext_pull.httpx.AsyncClient = factory
|
|
config = ExtConfig(
|
|
id="benchmark", label="benchmark", mode="timeseries", fields=[],
|
|
pull=PullConfig(url="https://example.test/rank", page_param="page", max_pages=PAGES + 1),
|
|
)
|
|
try:
|
|
started = time.perf_counter()
|
|
if shared:
|
|
rows = await ext_pull.fetch_rows_for_date(config, date(2026, 9, 1))
|
|
else:
|
|
for page in range(1, PAGES + 2):
|
|
payload = await ext_pull._request_json(config.pull, config.id, extra_params={"page": str(page)})
|
|
if not payload:
|
|
break
|
|
if page == 1:
|
|
rows = []
|
|
rows.extend(payload)
|
|
elapsed = time.perf_counter() - started
|
|
assert len(rows) == PAGES and requests == PAGES + 1
|
|
return elapsed, clients, requests
|
|
finally:
|
|
ext_pull.httpx.AsyncClient = original
|
|
|
|
|
|
async def main() -> None:
|
|
timings: dict[bool, list[float]] = {False: [], True: []}
|
|
for _ in range(RUNS):
|
|
for shared in (False, True):
|
|
elapsed, clients, requests = await run(shared)
|
|
timings[shared].append(elapsed)
|
|
print(f"{'shared' if shared else 'per-request'}: {elapsed:.4f}s, {requests} requests, {clients} clients")
|
|
print(f"median: per-request={statistics.median(timings[False]):.4f}s, shared={statistics.median(timings[True]):.4f}s")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|