# shared helpers for S3c bench (no secrets) set -euo pipefail log() { printf '[%s] %s\n' "$(date '+%Y-%m-%dT%H:%M:%S%z')" "$*"; } parse_mem_mib() { python3 - "$1" <<'PY' import re, sys s = sys.argv[1].split("/")[0].strip() m = re.match(r"([0-9.]+)\s*([A-Za-z]+)", s) if not m: print("0") raise SystemExit v, u = float(m.group(1)), m.group(2).lower() mult = {"b":1,"kib":1024,"kb":1000,"mib":1024**2,"mb":1000**2,"gib":1024**3,"gb":1000**3}.get(u) if not mult: print("0"); raise SystemExit print(f"{v * mult / (1024**2):.3f}") PY } cgroup_mib() { local c="$1" raw="" raw="$(docker exec "$c" sh -c 'cat /sys/fs/cgroup/memory.current 2>/dev/null || cat /sys/fs/cgroup/memory/memory.usage_in_bytes 2>/dev/null' 2>/dev/null || true)" if [[ -z "$raw" ]]; then echo "" return fi python3 -c "print(f'{int(\"$raw\")/(1024*1024):.3f}')" } sample_stats() { # sample_stats local out="$1" interval="$2" duration="$3" shift 3 mkdir -p "$(dirname "$out")" echo -e "ts_iso\tname\tmem_usage\tcpu_pct\tmem_mib\tcgroup_mib" > "$out" local end=$(( $(date +%s) + duration )) while [ "$(date +%s)" -lt "$end" ]; do local ts ts=$(date -u +%Y-%m-%dT%H:%M:%SZ) local line name mem cpu while IFS='|' read -r name mem cpu; do [[ -z "${name:-}" ]] && continue local mib cg mib="$(parse_mem_mib "$mem")" cg="$(cgroup_mib "$name")" printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$ts" "$name" "$mem" "$cpu" "$mib" "${cg:-}" >> "$out" done < <(docker stats --no-stream --format '{{.Name}}|{{.MemUsage}}|{{.CPUPerc}}' "$@" 2>/dev/null || true) sleep "$interval" done } sample_until_file() { # sample until a sentinel file exists, then extra_s more local out="$1" interval="$2" sentinel="$3" extra_s="$4" shift 4 mkdir -p "$(dirname "$out")" echo -e "ts_iso\tname\tmem_usage\tcpu_pct\tmem_mib\tcgroup_mib" > "$out" while [[ ! -f "$sentinel" ]]; do local ts name mem cpu mib cg ts=$(date -u +%Y-%m-%dT%H:%M:%SZ) while IFS='|' read -r name mem cpu; do [[ -z "${name:-}" ]] && continue mib="$(parse_mem_mib "$mem")" cg="$(cgroup_mib "$name")" printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$ts" "$name" "$mem" "$cpu" "$mib" "${cg:-}" >> "$out" done < <(docker stats --no-stream --format '{{.Name}}|{{.MemUsage}}|{{.CPUPerc}}' "$@" 2>/dev/null || true) sleep "$interval" done local end=$(( $(date +%s) + extra_s )) while [ "$(date +%s)" -lt "$end" ]; do local ts name mem cpu mib cg ts=$(date -u +%Y-%m-%dT%H:%M:%SZ) while IFS='|' read -r name mem cpu; do [[ -z "${name:-}" ]] && continue mib="$(parse_mem_mib "$mem")" cg="$(cgroup_mib "$name")" printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$ts" "$name" "$mem" "$cpu" "$mib" "${cg:-}" >> "$out" done < <(docker stats --no-stream --format '{{.Name}}|{{.MemUsage}}|{{.CPUPerc}}' "$@" 2>/dev/null || true) sleep "$interval" done } ensure_image() { # ensure_image local img="$1" note="${2:-}" local platform="linux/arm64" local how="local" if docker image inspect "$img" >/dev/null 2>&1; then local arch arch="$(docker image inspect --format '{{.Architecture}}' "$img")" if [[ "$arch" == "arm64" || "$arch" == "arm64/v8" ]]; then log "image present $img arch=$arch" [[ -n "$note" ]] && echo "$how" > "$note" return 0 fi log "image $img arch=$arch not arm64; re-pull" fi log "docker pull --platform $platform $img" if docker pull --platform "$platform" "$img"; then how="hub" [[ -n "$note" ]] && echo "$how" > "$note" return 0 fi local short="${img#docker.io/}" local mirror="docker.m.daocloud.io/${short}" log "primary pull failed; retry $mirror" docker pull --platform "$platform" "$mirror" docker tag "$mirror" "$img" how="daocloud_mirror" [[ -n "$note" ]] && echo "$how" > "$note" } image_meta() { local c="$1" docker inspect --format '{{.Config.Image}} {{index .RepoDigests 0}} {{.Image}}' "$c" 2>/dev/null || true } wait_http() { local url="$1" tries="${2:-40}" local i for i in $(seq 1 "$tries"); do if curl -sf --max-time 2 "$url" >/dev/null; then return 0 fi sleep 1 done return 1 }