From 298b9c80209650434d62e5c1ced76c1ba97a1840 Mon Sep 17 00:00:00 2001 From: ramseshk Date: Thu, 6 Aug 2026 06:31:16 +0000 Subject: [PATCH] Memory guard: 512MB hard cap, GC at 256MB, 2GB swap --- dashboard/server.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dashboard/server.py b/dashboard/server.py index 90532b8..3f27e46 100644 --- a/dashboard/server.py +++ b/dashboard/server.py @@ -30,6 +30,34 @@ sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from config.fee_tiers import get_perp_fees, PERPS_TIERS, STAKING_TIERS, STRATEGY_FEE_MODELS from common.risk import risk_summary from strategies.quant_report import compute_quant_report + +# ═══════════════════════════════════════════════════════════ +# Memory guard: cap RSS at 512MB, GC-aggressive at 256MB +# ═══════════════════════════════════════════════════════════ +import resource, gc, signal + +MEM_SOFT_LIMIT = 256 * 1024 * 1024 # 256 MB — force GC +MEM_HARD_LIMIT = 512 * 1024 * 1024 # 512 MB — terminate + +resource.setrlimit(resource.RLIMIT_AS, (MEM_HARD_LIMIT, MEM_HARD_LIMIT)) + +def check_memory(): + """Check RSS, force GC if over soft limit, raise if over hard limit.""" + try: + with open("/proc/self/status") as f: + for line in f: + if line.startswith("VmRSS:"): + rss_kb = int(line.split()[1]) + rss = rss_kb * 1024 + if rss > MEM_HARD_LIMIT: + print(f"[CRIT] RSS {rss_kb // 1024}MB > 512MB — exiting", flush=True) + os._exit(1) + if rss > MEM_SOFT_LIMIT: + gc.collect() + gc.collect() + return + except Exception: + pass import uvicorn # ═══════════════════════════════════════════════════════════ @@ -110,6 +138,7 @@ def broadcast_loop(): """Continuously read metrics and broadcast to all clients.""" while True: time.sleep(1) + check_memory() data = read_metrics() payload = json.dumps(data, default=str) for ws in list(connected_clients):