from __future__ import annotations import argparse import asyncio import json import sys import time from pathlib import Path from types import SimpleNamespace from unittest.mock import patch ROOT = Path(__file__).resolve().parents[1] BACKEND = ROOT / "backend" for path in (str(BACKEND), str(ROOT)): if path not in sys.path: sys.path.insert(0, path) import bot.app.web.subscription_webapp # noqa: E402,F401 from bot.app.web.admin_api_impl import stats as admin_stats_module # noqa: E402 from bot.handlers.admin.sync_admin import ( # noqa: E402 _description_matches, _subscription_update_delta, ) from bot.middlewares import profile_sync as profile_sync_module # noqa: E402 from bot.services import panel_api_service # noqa: E402 from bot.services.panel_api_service import PanelApiService # noqa: E402 from bot.services.tariff_worker import TariffTrafficWorker # noqa: E402 from bot.utils import config_link # noqa: E402 from bot.utils.config_link import prepare_config_links # noqa: E402 from bot.utils.ttl_cache import AsyncTTLCache # noqa: E402 DEFAULT_USER_SIZES = (200, 500, 1000, 5000, 10000) def estimated_panel_user_pages(users: int, page_size: int = 1000) -> int: if users <= 0: return 1 # get_all_panel_users stops on a short/empty page, so exact page multiples # need one final empty-page request. return users // page_size + 1 class FakePanel: def __init__(self, users: int): self.calls = 0 self.stats = { "topUsers": [ { "username": f"user_{index}", "total": index + 1, } for index in range(users) ] } async def get_node_users_bandwidth_stats(self, node_uuid: str, *, start: str, end: str): self.calls += 1 return self.stats class FakeBulkPanel: def __init__(self, users: int): self.calls = 0 self.users = [ {"uuid": f"panel-{index}", "username": f"user_{index}"} for index in range(users) ] async def get_all_panel_users(self, page_size: int = 100, log_responses: bool = False): self.calls += 1 return self.users async def bench_premium_usage(users: int) -> dict: panel = FakePanel(users) worker = TariffTrafficWorker( settings=SimpleNamespace(), session_factory=SimpleNamespace(), panel_service=panel, subscription_service=SimpleNamespace(), ) started = time.perf_counter() checksum = 0 for index in range(users): checksum += await worker._premium_usage_for_user( f"uuid_{index}", ["node-1"], "2026-05-01", "2026-05-20", panel_username=f"user_{index}", ) elapsed = time.perf_counter() - started return { "seconds": elapsed, "panel_calls": panel.calls, "checksum": checksum, } async def bench_panel_user_prefetch(users: int) -> dict: panel = FakeBulkPanel(users) worker = TariffTrafficWorker( settings=SimpleNamespace(TARIFF_WORKER_BULK_PANEL_FETCH_THRESHOLD=50), session_factory=SimpleNamespace(), panel_service=panel, subscription_service=SimpleNamespace(), ) subs = [SimpleNamespace(panel_user_uuid=f"panel-{index}") for index in range(users)] started = time.perf_counter() by_uuid = await worker._prefetch_panel_users_by_uuid(subs) elapsed = time.perf_counter() - started return { "seconds": elapsed, "service_calls": panel.calls, "matched": len(by_uuid or {}), "legacy_user_get_calls": users, "estimated_bulk_http_pages": estimated_panel_user_pages(users), } async def bench_panel_sync_startup(users: int) -> dict: end_date = "2026-06-20T12:00:00+00:00" from datetime import datetime, timezone parsed_end_date = datetime.fromisoformat(end_date).astimezone(timezone.utc) started = time.perf_counter() subscription_writes = 0 description_patches = 0 for index in range(users): desired_description = f"user{index}@example.test\nusername_{index}" current_description = f"user{index}@example.test username_{index}" if not _description_matches(current_description, desired_description): description_patches += 1 subscription = SimpleNamespace( user_id=index, panel_user_uuid=f"panel-{index}", end_date=parsed_end_date, is_active=True, status_from_panel="ACTIVE", ) delta = _subscription_update_delta( subscription, { "user_id": index, "panel_user_uuid": f"panel-{index}", "end_date": parsed_end_date, "is_active": True, "status_from_panel": "ACTIVE", }, ) if delta: subscription_writes += 1 elapsed = time.perf_counter() - started return { "seconds": elapsed, "panel_get_pages_estimate": estimated_panel_user_pages(users), "legacy_user_lookup_queries_estimate": users * 3, "optimized_user_lookup_queries_estimate": 1, "legacy_subscription_lookup_queries_estimate": users, "optimized_subscription_lookup_queries_estimate": 1, "legacy_subscription_write_attempts": users, "optimized_subscription_writes": subscription_writes, "description_panel_patches": description_patches, } async def bench_panel_user_cache(users: int) -> dict: settings = SimpleNamespace( PANEL_API_URL="https://panel.example.test/api", PANEL_API_KEY="key", USER_HWID_DEVICE_LIMIT=None, PANEL_USER_CACHE_TTL_SECONDS=60, PANEL_DEVICES_CACHE_TTL_SECONDS=60, PANEL_ALL_USERS_CACHE_TTL_SECONDS=60, PANEL_ALL_USERS_PAGE_SIZE=1000, REDIS_URL=None, REDIS_KEY_PREFIX="bench", ) service = PanelApiService(settings) calls = 0 async def fake_request(method, endpoint, log_full_response=False, **kwargs): nonlocal calls calls += 1 await asyncio.sleep(0.001) return {"response": {"uuid": "panel-user", "username": "cached"}} service._request = fake_request started = time.perf_counter() await asyncio.gather(*(service.get_user_by_uuid("panel-user") for _ in range(users))) elapsed = time.perf_counter() - started return { "seconds": elapsed, "panel_calls": calls, "legacy_panel_calls": users, } async def bench_panel_all_users_cache(users: int) -> dict: settings = SimpleNamespace( PANEL_API_URL="https://panel.example.test/api", PANEL_API_KEY="key", USER_HWID_DEVICE_LIMIT=None, PANEL_USER_CACHE_TTL_SECONDS=60, PANEL_DEVICES_CACHE_TTL_SECONDS=60, PANEL_ALL_USERS_CACHE_TTL_SECONDS=60, PANEL_ALL_USERS_PAGE_SIZE=1000, REDIS_URL=None, REDIS_KEY_PREFIX="bench", ) service = PanelApiService(settings) panel_users = [{"uuid": f"panel-{index}"} for index in range(users)] calls = 0 async def fake_request(method, endpoint, log_full_response=False, **kwargs): nonlocal calls calls += 1 await asyncio.sleep(0.001) params = kwargs.get("params") or {} size = int(params.get("size", 100)) start = int(params.get("start", 0)) return {"response": {"users": panel_users[start : start + size]}} service._request = fake_request started = time.perf_counter() first, second = await asyncio.gather( service.get_all_panel_users(), service.get_all_panel_users(), ) elapsed = time.perf_counter() - started pages = estimated_panel_user_pages(users) return { "seconds": elapsed, "panel_calls": calls, "legacy_panel_calls": pages * 2, "users_first": len(first or []), "users_second": len(second or []), } async def bench_panel_devices_cache(users: int) -> dict: settings = SimpleNamespace( PANEL_API_URL="https://panel.example.test/api", PANEL_API_KEY="key", USER_HWID_DEVICE_LIMIT=None, PANEL_USER_CACHE_TTL_SECONDS=60, PANEL_DEVICES_CACHE_TTL_SECONDS=60, PANEL_ALL_USERS_CACHE_TTL_SECONDS=60, PANEL_ALL_USERS_PAGE_SIZE=1000, REDIS_URL=None, REDIS_KEY_PREFIX="bench", ) service = PanelApiService(settings) calls = 0 async def fake_request(method, endpoint, log_full_response=False, **kwargs): nonlocal calls calls += 1 await asyncio.sleep(0.001) return {"response": [{"hwid": "device-1"}]} service._request = fake_request started = time.perf_counter() await asyncio.gather(*(service.get_user_devices("panel-user") for _ in range(users))) elapsed = time.perf_counter() - started return { "seconds": elapsed, "panel_calls": calls, "legacy_panel_calls": users, } async def bench_ttl_singleflight(users: int) -> dict: settings = SimpleNamespace(REDIS_URL="redis://example", REDIS_KEY_PREFIX="bench") cache = AsyncTTLCache(ttl_seconds=60, settings=settings, namespace="singleflight") calls = 0 async def loader(): nonlocal calls calls += 1 await asyncio.sleep(0.001) return {"value": 42} async def fake_get(settings, key): return None async def fake_set(settings, key, value, ttl): return None started = time.perf_counter() with ( patch("bot.infra.redis.cache_get_json", new=fake_get), patch("bot.infra.redis.cache_set_json", new=fake_set), ): await asyncio.gather(*(cache.get_or_load("same-key", loader) for _ in range(users))) elapsed = time.perf_counter() - started return { "seconds": elapsed, "loader_calls": calls, } class FakeAdminStatsPanel: def __init__(self): self.calls = { "system": 0, "bandwidth": 0, "nodes": 0, "nodes_bandwidth": 0, "online": 0, } async def get_system_stats(self): self.calls["system"] += 1 await asyncio.sleep(0.001) return {"users": {"totalUsers": 10}} async def get_bandwidth_stats(self): self.calls["bandwidth"] += 1 await asyncio.sleep(0.001) return {"current": 123} async def get_nodes_statistics(self): self.calls["nodes"] += 1 await asyncio.sleep(0.001) return {"nodes": []} async def get_nodes_bandwidth_usage(self, *, start: str, end: str, top_nodes_limit: int = 64): self.calls["nodes_bandwidth"] += 1 await asyncio.sleep(0.001) return {"topNodes": []} async def get_nodes_online_lookups(self): self.calls["online"] += 1 await asyncio.sleep(0.001) return {"byUuid": {}, "byName": {}} async def bench_admin_stats_cache(users: int) -> dict: admin_stats_module._ADMIN_PANEL_STATS_CACHES.clear() settings = SimpleNamespace( ADMIN_PANEL_STATS_CACHE_TTL_SECONDS=60, REDIS_URL=None, REDIS_KEY_PREFIX="bench", ) panel = FakeAdminStatsPanel() started = time.perf_counter() await asyncio.gather( *(admin_stats_module._load_admin_panel_stats(None, settings, panel) for _ in range(users)) ) elapsed = time.perf_counter() - started return { "seconds": elapsed, "panel_endpoint_calls": sum(panel.calls.values()), "legacy_panel_endpoint_calls": users * len(panel.calls), } async def bench_admin_db_stats_cache(users: int) -> dict: admin_stats_module._ADMIN_DB_STATS_CACHES.clear() settings = SimpleNamespace( ADMIN_DB_STATS_CACHE_TTL_SECONDS=60, REDIS_URL=None, REDIS_KEY_PREFIX="bench", ) dal_calls = 0 class FakeSessionFactory: def __call__(self): return self async def __aenter__(self): return SimpleNamespace() async def __aexit__(self, exc_type, exc, tb): return None async def fake_user_stats(session): nonlocal dal_calls dal_calls += 1 await asyncio.sleep(0.001) return { "total_users": users, "banned_users": 0, "active_today": 0, "paid_subscriptions": users, "trial_users": 0, "inactive_users": 0, "referral_users": 0, } async def fake_financial_stats(session): nonlocal dal_calls dal_calls += 1 await asyncio.sleep(0.001) return { "today_revenue": 0.0, "week_revenue": 0.0, "month_revenue": 0.0, "all_time_revenue": 0.0, "today_payments_count": 0, "daily_series": [], } async def fake_sync_status(session): nonlocal dal_calls dal_calls += 1 await asyncio.sleep(0.001) return SimpleNamespace( status="success", last_sync_time=None, details=None, users_processed_from_panel=users, subscriptions_synced=users, ) async def fake_recent_payments(session, limit=10): nonlocal dal_calls dal_calls += 1 await asyncio.sleep(0.001) return [] started = time.perf_counter() with ( patch.object(admin_stats_module.user_dal, "get_enhanced_user_statistics", fake_user_stats), patch.object( admin_stats_module.payment_dal, "get_financial_statistics", fake_financial_stats ), patch.object(admin_stats_module.panel_sync_dal, "get_panel_sync_status", fake_sync_status), patch.object( admin_stats_module.payment_dal, "get_recent_payment_logs_with_user", fake_recent_payments, ), ): await asyncio.gather( *( admin_stats_module._load_admin_db_stats(settings, FakeSessionFactory()) for _ in range(users) ) ) elapsed = time.perf_counter() - started return { "seconds": elapsed, "dal_loader_calls": dal_calls, "optimized_db_round_trips_per_miss_estimate": 6, "optimized_db_round_trips_with_cache_estimate": 6, "legacy_db_round_trips_estimate": users * 15, } async def bench_profile_sync_guard(users: int) -> dict: profile_sync_module._LOCAL_PROFILE_SYNC_CHECKS.clear() settings = SimpleNamespace( PROFILE_SYNC_CACHE_TTL_SECONDS=900, REDIS_URL=None, REDIS_KEY_PREFIX="bench", ) allowed_checks = 0 started = time.perf_counter() for _ in range(users): if not await profile_sync_module._profile_sync_recently_checked(settings, 42): allowed_checks += 1 await profile_sync_module._mark_profile_sync_checked(settings, 42) elapsed = time.perf_counter() - started return { "seconds": elapsed, "profile_checks_allowed": allowed_checks, "legacy_profile_checks": users, } async def bench_crypt4(users: int) -> dict: config_link._CRYPT4_LINK_CACHES.clear() settings = SimpleNamespace( CRYPT4_ENABLED=True, CRYPT4_REDIRECT_URL="", CRYPT4_LINK_CACHE_TTL_SECONDS=3600, PANEL_API_URL="https://panel.example.test/api", PANEL_API_KEY="key", USER_HWID_DEVICE_LIMIT=None, ) calls = 0 async def fake_encrypt(self, raw_link: str): nonlocal calls calls += 1 await asyncio.sleep(0.001) return "happ://crypt4/encrypted" async def fake_close(self): return None started = time.perf_counter() with ( patch.object(panel_api_service.PanelApiService, "encrypt_happ_link", new=fake_encrypt), patch.object(panel_api_service.PanelApiService, "close_session", new=fake_close), ): await asyncio.gather( *( prepare_config_links(settings, "https://panel.example.test/sub/user") for _ in range(users) ) ) elapsed = time.perf_counter() - started return { "seconds": elapsed, "panel_calls": calls, } async def run_suite(user_sizes: tuple[int, ...]) -> dict: results: dict[str, dict] = {} for users in user_sizes: results[str(users)] = { "panel_sync_startup": await bench_panel_sync_startup(users), "panel_user_bulk_prefetch": await bench_panel_user_prefetch(users), "panel_all_users_cache": await bench_panel_all_users_cache(users), "panel_user_cache": await bench_panel_user_cache(users), "panel_devices_cache": await bench_panel_devices_cache(users), "premium_usage_1_node": await bench_premium_usage(users), "ttl_cache_cold_single_key": await bench_ttl_singleflight(users), "admin_stats_cache": await bench_admin_stats_cache(users), "admin_db_stats_cache": await bench_admin_db_stats_cache(users), "profile_sync_guard": await bench_profile_sync_guard(users), "crypt4_same_link": await bench_crypt4(users), } return results def _print_table(results: dict[str, dict]) -> None: print( "users | bulk_pages_est | premium_usage_s | premium_panel_calls | " "sync_db_reads_est | sync_db_writes | user_cache_calls | " "all_users_calls | device_cache_calls | admin_panel_calls | admin_db_reads_est | " "crypt4_panel_calls" ) print("-" * 177) for users, data in results.items(): sync_optimized_reads = ( data["panel_sync_startup"]["optimized_user_lookup_queries_estimate"] + data["panel_sync_startup"]["optimized_subscription_lookup_queries_estimate"] ) print( f"{users:>5} | " f"{data['panel_user_bulk_prefetch']['estimated_bulk_http_pages']:>14} | " f"{data['premium_usage_1_node']['seconds']:>15.6f} | " f"{data['premium_usage_1_node']['panel_calls']:>19} | " f"{sync_optimized_reads:>17} | " f"{data['panel_sync_startup']['optimized_subscription_writes']:>14} | " f"{data['panel_user_cache']['panel_calls']:>16} | " f"{data['panel_all_users_cache']['panel_calls']:>15} | " f"{data['panel_devices_cache']['panel_calls']:>18} | " f"{data['admin_stats_cache']['panel_endpoint_calls']:>17} | " f"{data['admin_db_stats_cache']['optimized_db_round_trips_with_cache_estimate']:>18} | " f"{data['crypt4_same_link']['panel_calls']:>18}" ) def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Run bot performance microbenchmarks.") parser.add_argument( "--users", default=",".join(str(value) for value in DEFAULT_USER_SIZES), help="Comma-separated user counts. Default: 200,500,1000,5000,10000", ) parser.add_argument("--json", action="store_true", help="Print JSON only.") return parser.parse_args() def main() -> None: args = parse_args() user_sizes = tuple(int(part.strip()) for part in args.users.split(",") if part.strip()) results = asyncio.run(run_suite(user_sizes)) if args.json: print(json.dumps({"results": results}, ensure_ascii=False)) return _print_table(results) print() print(json.dumps({"results": results}, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()