125
scripts/docker-benchmark.sh
Normal file
125
scripts/docker-benchmark.sh
Normal file
@@ -0,0 +1,125 @@
|
||||
#!/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"
|
||||
Reference in New Issue
Block a user