#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Бенчмарк задержки перехвата MCP Sentinel с прогревом и расчётом перцентилей.""" import time import statistics import json import os from pathlib import Path import sys ROOT = Path(__file__).resolve().parent if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from sentinel import MCPSentinel def run_benchmark(warmup_n=20, measure_n=100, ledger=False): ledger_file = "test_benchmark_ledger.jsonl" if ledger else None if ledger_file and os.path.exists(ledger_file): try: os.remove(ledger_file) except Exception: pass sentinel = MCPSentinel(ledger_path=ledger_file) samples = [ {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "read_file", "arguments": {"path": "safe.txt"}}}, {"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "read_file", "arguments": {"path": "../../../etc/passwd"}}}, {"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "execute_query", "arguments": {"query": "SELECT * FROM users WHERE id = 1"}}}, {"jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": {"name": "execute_query", "arguments": {"query": "DROP TABLE users"}}}, {"jsonrpc": "2.0", "id": 5, "method": "tools/call", "params": {"name": "bash", "arguments": {"cmd": "ls -la"}}}, ] # 1. Прогрев for i in range(warmup_n): req = samples[i % len(samples)] sentinel.process_incoming_jsonrpc(json.dumps(req)) # 2. Измерения latencies_ms = [] for i in range(measure_n): req = samples[i % len(samples)] raw = json.dumps(req) t0 = time.perf_counter() sentinel.process_incoming_jsonrpc(raw) t1 = time.perf_counter() latencies_ms.append((t1 - t0) * 1000.0) if ledger_file and os.path.exists(ledger_file): try: os.remove(ledger_file) except Exception: pass latencies_sorted = sorted(latencies_ms) median = statistics.median(latencies_ms) mean = statistics.mean(latencies_ms) p95 = latencies_sorted[int(measure_n * 0.95)] p99 = latencies_sorted[int(measure_n * 0.99)] min_l = min(latencies_ms) max_l = max(latencies_ms) mode_name = "С ГОСТ-журналированием" if ledger else "Чистый перехват (in-memory)" print(f"MCP Sentinel Latency Benchmark [{mode_name}] (N={measure_n}, Warmup={warmup_n}):") print(f" Медиана (p50): {round(median, 3)} мс") print(f" Среднее: {round(mean, 3)} мс") print(f" 95-й перцентиль (p95): {round(p95, 3)} мс") print(f" 99-й перцентиль (p99): {round(p99, 3)} мс") print(f" Мин / Макс: {round(min_l, 3)} мс / {round(max_l, 3)} мс\n") return { "mode": mode_name, "n": measure_n, "median_ms": round(median, 3), "mean_ms": round(mean, 3), "p95_ms": round(p95, 3), "p99_ms": round(p99, 3), "min_ms": round(min_l, 3), "max_ms": round(max_l, 3) } if __name__ == "__main__": run_benchmark(warmup_n=20, measure_n=100, ledger=False) run_benchmark(warmup_n=20, measure_n=100, ledger=True)