From 1e2e34ff66fd390f567f4a727a12ee7fda2eebcc Mon Sep 17 00:00:00 2001 From: RohanExploit <178623867+RohanExploit@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:25:06 +0000 Subject: [PATCH 1/3] refactor: optimize get_leaderboard and get_stats serialization caching Implemented serialization caching in `get_leaderboard` and `get_stats` to improve response times. By serializing the output dictionaries to JSON strings before caching them, and returning a raw `fastapi.Response` with `media_type="application/json"`, we bypass the repetitive validation and JSON serialization overhead associated with `JSONResponse` on cache hits. Benchmark: - JSONResponse: ~1.5152s (10000 iterations) - Raw Response with pre-serialized JSON: ~0.0312s (10000 iterations) --- backend/routers/utility.py | 17 +++++++++------- backend/tests/benchmark_serialization.py | 25 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 backend/tests/benchmark_serialization.py diff --git a/backend/routers/utility.py b/backend/routers/utility.py index 218e5552..29a91573 100644 --- a/backend/routers/utility.py +++ b/backend/routers/utility.py @@ -1,9 +1,10 @@ -from fastapi import APIRouter, Depends, HTTPException, Query +from fastapi import APIRouter, Depends, HTTPException, Query, Response from fastapi.responses import JSONResponse from sqlalchemy.orm import Session from sqlalchemy import func, case from datetime import datetime, timezone import logging +import json from backend.database import get_db from backend.models import Issue @@ -51,7 +52,7 @@ def health(): def get_stats(db: Session = Depends(get_db)): cached_stats = recent_issues_cache.get("stats") if cached_stats: - return JSONResponse(content=cached_stats) + return Response(content=cached_stats, media_type="application/json") # Optimized: Single aggregate query for both category breakdowns and system-wide totals # This eliminates a redundant database roundtrip @@ -84,9 +85,10 @@ def get_stats(db: Session = Depends(get_db)): ) data = response.model_dump(mode='json') - recent_issues_cache.set(data, "stats") + json_data = json.dumps(data) + recent_issues_cache.set(json_data, "stats") - return response + return Response(content=json_data, media_type="application/json") @router.get("/ml-status", response_model=MLStatusResponse) async def ml_status(): @@ -116,7 +118,7 @@ def get_leaderboard(db: Session = Depends(get_db)): cache_key = "leaderboard" cached_data = recent_issues_cache.get(cache_key) if cached_data: - return JSONResponse(content=cached_data) + return Response(content=cached_data, media_type="application/json") # Group by user_email, count issues, sum upvotes # Optimization: Only select needed columns and use aggregation @@ -149,10 +151,11 @@ def get_leaderboard(db: Session = Depends(get_db)): ).model_dump(mode='json')) response_data = {"leaderboard": leaderboard_data} + json_data = json.dumps(response_data) # Cache for 5 minutes to reduce DB load on frequent hits - recent_issues_cache.set(response_data, cache_key) + recent_issues_cache.set(json_data, cache_key) - return response_data + return Response(content=json_data, media_type="application/json") @router.get("/mh/rep-contacts") diff --git a/backend/tests/benchmark_serialization.py b/backend/tests/benchmark_serialization.py new file mode 100644 index 00000000..9382ce33 --- /dev/null +++ b/backend/tests/benchmark_serialization.py @@ -0,0 +1,25 @@ +import time +import json +from fastapi import Response +from fastapi.responses import JSONResponse + +data = {"leaderboard": [{"user_email": "abc@def.com", "reports_count": 10, "total_upvotes": 50, "rank": 1} for _ in range(100)]} +json_data = json.dumps(data) + +def test_jsonresponse(): + start = time.perf_counter() + for _ in range(10000): + # JSONResponse internally calls json.dumps + resp = JSONResponse(content=data) + _ = resp.body + return time.perf_counter() - start + +def test_rawresponse(): + start = time.perf_counter() + for _ in range(10000): + resp = Response(content=json_data, media_type="application/json") + _ = resp.body + return time.perf_counter() - start + +print(f"JSONResponse: {test_jsonresponse():.4f}s") +print(f"Response with pre-serialized JSON: {test_rawresponse():.4f}s") From 583c95da30bab374c3f77f76dd45e2cf5a5e2f70 Mon Sep 17 00:00:00 2001 From: Rohan Gaikwad Date: Mon, 30 Mar 2026 21:57:16 +0530 Subject: [PATCH 2/3] Update backend/routers/utility.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- backend/routers/utility.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/routers/utility.py b/backend/routers/utility.py index 29a91573..5a61d43b 100644 --- a/backend/routers/utility.py +++ b/backend/routers/utility.py @@ -1,5 +1,4 @@ from fastapi import APIRouter, Depends, HTTPException, Query, Response -from fastapi.responses import JSONResponse from sqlalchemy.orm import Session from sqlalchemy import func, case from datetime import datetime, timezone From 83320710d007abf31b054b446a52f84d9a7ed532 Mon Sep 17 00:00:00 2001 From: Rohan Gaikwad Date: Mon, 30 Mar 2026 21:57:41 +0530 Subject: [PATCH 3/3] Update backend/tests/benchmark_serialization.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- backend/tests/benchmark_serialization.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/tests/benchmark_serialization.py b/backend/tests/benchmark_serialization.py index 9382ce33..ca724f1c 100644 --- a/backend/tests/benchmark_serialization.py +++ b/backend/tests/benchmark_serialization.py @@ -21,5 +21,6 @@ def test_rawresponse(): _ = resp.body return time.perf_counter() - start -print(f"JSONResponse: {test_jsonresponse():.4f}s") -print(f"Response with pre-serialized JSON: {test_rawresponse():.4f}s") +if __name__ == "__main__": + print(f"JSONResponse: {test_jsonresponse():.4f}s") + print(f"Response with pre-serialized JSON: {test_rawresponse():.4f}s")