#!/usr/bin/env bash # Hiệu năng lidar_manager_web trong container Docker. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # shellcheck source=docker-lib.sh source "$ROOT/scripts/docker-lib.sh" docker_cmd NAME="${1:-lidar-manager-limited}" BASE="${2:-http://127.0.0.1:8080}" REQUESTS="${BENCH_REQUESTS:-100}" WARMUP="${BENCH_WARMUP:-10}" if ! "${DOCKER[@]}" ps --format '{{.Names}}' | grep -qx "$NAME"; then echo "Container '$NAME' không chạy. Chạy: sudo docker compose up -d --build" >&2 exit 1 fi echo "=== PhenikaaX lidar_manager_web — benchmark container ===" echo "Container: $NAME" echo "URL: $BASE" echo "Requests/endpoint: $REQUESTS (warmup $WARMUP)" echo echo "=== Docker stats (snapshot) ===" "${DOCKER[@]}" stats --no-stream --format \ 'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}' "$NAME" echo print_container_limits "$NAME" echo echo "=== Process trong container ===" "${DOCKER[@]}" exec "$NAME" sh -c ' echo "PID RSS_KB VSZ_KB CMD" ps -o pid,rss,vsz,cmd -C lidar_manager_web 2>/dev/null || ps aux | grep lidar_manager_web | grep -v grep echo echo "--- /proc/meminfo (head) ---" head -5 /proc/meminfo echo "--- nproc ---" nproc ' echo bench_endpoint() { local label="$1" local method="$2" local path="$3" local body="${4:-}" python3 - "$label" "$method" "$BASE$path" "$REQUESTS" "$WARMUP" "$body" <<'PY' import json import statistics import sys import time import urllib.error import urllib.request label, method, url, n_req, n_warm, body = sys.argv[1:7] n_req = int(n_req) n_warm = int(n_warm) data = body.encode() if body else None headers = {"Content-Type": "application/json"} if data else {} def once(): req = urllib.request.Request(url, data=data, headers=headers, method=method) t0 = time.perf_counter() with urllib.request.urlopen(req, timeout=10) as resp: resp.read() return (time.perf_counter() - t0) * 1000.0 for _ in range(n_warm): try: once() except Exception: pass samples = [] errors = 0 for _ in range(n_req): try: samples.append(once()) except Exception: errors += 1 if not samples: print(f"{label}: FAIL (no successful samples, errors={errors})") else: samples.sort() def pct(p): i = max(0, min(len(samples) - 1, int(len(samples) * p / 100.0) - 1)) return samples[i] print( f"{label}: ok={len(samples)} err={errors} " f"min={samples[0]:.2f}ms p50={pct(50):.2f}ms p95={pct(95):.2f}ms " f"max={samples[-1]:.2f}ms avg={statistics.mean(samples):.2f}ms" ) PY } echo "=== HTTP latency (ms) ===" if ! curl -sf "$BASE/api/health" >/dev/null; then echo "Server không phản hồi tại $BASE" >&2 exit 1 fi bench_endpoint "GET /api/health" GET "/api/health" bench_endpoint "GET /api/state" GET "/api/state" bench_endpoint "GET /api/missions" GET "/api/missions" bench_endpoint "GET /api/mission_queue" GET "/api/mission_queue" bench_endpoint "GET /api/v2.0.0/mission_queue" GET "/api/v2.0.0/mission_queue" bench_endpoint "GET / (index.html)" GET "/" bench_endpoint "GET /missions.js" GET "/missions.js" MID="$(curl -sf "$BASE/api/missions" | python3 -c "import json,sys; m=json.load(sys.stdin).get('missions',[]); print(m[0]['id'] if m else '')")" if [[ -n "$MID" ]]; then bench_endpoint "POST /api/v2.0.0/mission_queue" POST "/api/v2.0.0/mission_queue" \ "{\"mission_id\":\"$MID\",\"priority\":0}" fi echo echo "=== Docker stats (sau benchmark) ===" "${DOCKER[@]}" stats --no-stream --format \ 'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}' "$NAME"