161 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Common helpers for benchmark orchestrators.
# Usage: source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../scripts/common/lib.sh"
set -Eeuo pipefail
# Resolve repository root relative to this file.
_COMMON_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${_COMMON_LIB_DIR}/../.." && pwd)"
# -----------------------------------------------------------------------------
# Logging
# -----------------------------------------------------------------------------
LOG_FILE=""
log_init() {
local log_path="$1"
LOG_FILE="$log_path"
mkdir -p "$(dirname "$LOG_FILE")"
: > "$LOG_FILE"
}
log() {
local msg="[$(date --iso-8601=seconds)] $*"
echo "$msg"
if [[ -n "${LOG_FILE:-}" ]]; then
echo "$msg" >> "$LOG_FILE"
fi
}
# -----------------------------------------------------------------------------
# Result directories
# -----------------------------------------------------------------------------
ensure_result_root() {
local result_root="$1"
mkdir -p "${result_root}/logs"
mkdir -p "${result_root}/raw_outputs"
echo "$result_root"
}
# -----------------------------------------------------------------------------
# Server health check
# -----------------------------------------------------------------------------
health_check() {
local host="${1:-127.0.0.1}"
local port="${2:-30000}"
local max_wait="${3:-120}"
for ((i = 1; i <= max_wait; i++)); do
if curl --fail --silent --show-error --max-time 5 "http://${host}:${port}/health" >/dev/null 2>&1; then
return 0
fi
sleep 1
done
return 1
}
# -----------------------------------------------------------------------------
# Git metadata
# -----------------------------------------------------------------------------
git_commit() {
( cd "$ROOT_DIR" && git rev-parse --short HEAD 2>/dev/null || echo "unknown" )
}
git_dirty() {
(
cd "$ROOT_DIR" || exit 1
if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then
echo "dirty"
else
echo "clean"
fi
)
}
# -----------------------------------------------------------------------------
# results.json metadata
# -----------------------------------------------------------------------------
write_metadata_json() {
local output_path="$1"
local experiment="$2"
local run_id="$3"
local model="$4"
local backend="$5"
local engine="$6"
local hardware="$7"
local accelerator="$8"
local chip="$9"
local script="${10}"
local env_path="${11:-}"
local description="${12:-}"
mkdir -p "$(dirname "$output_path")"
"${PYTHON:-python3}" - "$output_path" "$experiment" "$run_id" "$model" "$backend" "$engine" "$hardware" "$accelerator" "$chip" "$script" "$env_path" "$description" "$(date --iso-8601=seconds)" "$(git_commit)" "$(git_dirty)" <<'PY'
import json, sys
(out, experiment, run_id, model, backend, engine, hardware, accelerator,
chip, script, env_path, description, timestamp, git_commit,
git_dirty) = sys.argv[1:16]
data = {
"metadata": {
"experiment": experiment,
"run_id": run_id,
"timestamp": timestamp,
"model": model,
"backend": backend,
"engine": engine,
"hardware": hardware,
"accelerator": accelerator,
"chip": chip,
"script": script,
"env": env_path,
"git_commit": git_commit,
"git_dirty": git_dirty,
"description": description,
},
"config": {},
"scenarios": [],
}
with open(out, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
PY
}
# -----------------------------------------------------------------------------
# JSON append helper (naive but sufficient for small result JSONs)
# -----------------------------------------------------------------------------
append_scenario_to_json() {
local json_path="$1"
local scenario_json="$2"
if [[ ! -f "$json_path" ]]; then
echo "ERROR: $json_path not found" >&2
return 1
fi
# Use Python for safe JSON manipulation.
"${PYTHON:-python3}" - "$json_path" "$scenario_json" <<'PY'
import json
import sys
json_path = sys.argv[1]
scenario_json = sys.argv[2]
with open(json_path, "r", encoding="utf-8") as f:
data = json.load(f)
scenario = json.loads(scenario_json)
data["scenarios"].append(scenario)
with open(json_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
PY
}