mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-22 18:25:32 -04:00
216 lines
6.0 KiB
Bash
Executable File
216 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Cold OpenCode clone/install/typecheck benchmark for a fresh Ubuntu x86_64 VM.
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_URL="${BENCH_REPO_URL:-https://github.com/anomalyco/opencode.git}"
|
|
COMMIT="${BENCH_COMMIT:-08fb47373509ba64b13441061314eeacf4264f51}"
|
|
BUN_VERSION="${BENCH_BUN_VERSION:-1.3.14}"
|
|
NODE_VERSION="${BENCH_NODE_VERSION:-24.14.1}"
|
|
ROOT="${BENCH_ROOT:-/tmp/opencode-provider-benchmark}"
|
|
KEEP_ROOT="${BENCH_KEEP_ROOT:-false}"
|
|
PROVIDER="${BENCH_PROVIDER:-unknown}"
|
|
REGION="${BENCH_REGION:-unknown}"
|
|
|
|
declare -A PHASE_MS=()
|
|
|
|
timestamp() {
|
|
date +%s%N
|
|
}
|
|
|
|
phase() {
|
|
local name="$1"
|
|
shift
|
|
local start end
|
|
start="$(timestamp)"
|
|
set +e
|
|
"$@"
|
|
local status=$?
|
|
set -e
|
|
end="$(timestamp)"
|
|
PHASE_MS["$name"]="$(( (end - start) / 1000000 ))"
|
|
printf 'BENCH_PHASE\t%s\t%s\n' "$name" "${PHASE_MS[$name]}"
|
|
return "$status"
|
|
}
|
|
|
|
seconds() {
|
|
awk -v milliseconds="${1:-0}" 'BEGIN { printf "%.3fs", milliseconds / 1000 }'
|
|
}
|
|
|
|
render_table() {
|
|
local result="$1"
|
|
local typecheck="—"
|
|
local workload="—"
|
|
if [[ -n "${PHASE_MS[typecheck]:-}" ]]; then
|
|
typecheck="$(seconds "${PHASE_MS[typecheck]}")"
|
|
fi
|
|
if [[ "$result" == "✅" ]]; then
|
|
workload="$(seconds "$(( ${PHASE_MS[clone]} + ${PHASE_MS[install]} + ${PHASE_MS[typecheck]} ))")"
|
|
elif [[ -n "${PHASE_MS[typecheck]:-}" ]]; then
|
|
typecheck="${typecheck} (failed)"
|
|
fi
|
|
local memory
|
|
memory="$(awk '/MemTotal/{printf "%.2f GiB", $2 / 1048576}' /proc/meminfo)"
|
|
local cpu_model
|
|
cpu_model="$(awk -F: '/model name/{gsub(/^[ \t]+/, "", $2); print $2; exit}' /proc/cpuinfo)"
|
|
printf '\n| Provider | CPU / RAM | Region / CPU | Clone | Install | Typecheck | Workload total | Result |\n'
|
|
printf '|---|---|---|---:|---:|---:|---:|---|\n'
|
|
printf '| **%s** | %s CPU / %s | %s, %s | %s | %s | %s | %s | %s |\n' \
|
|
"$PROVIDER" \
|
|
"$(getconf _NPROCESSORS_ONLN)" \
|
|
"$memory" \
|
|
"$REGION" \
|
|
"$cpu_model" \
|
|
"$(seconds "${PHASE_MS[clone]:-0}")" \
|
|
"$(seconds "${PHASE_MS[install]:-0}")" \
|
|
"$typecheck" \
|
|
"$workload" \
|
|
"$result"
|
|
}
|
|
|
|
if [[ "$(id -u)" -eq 0 ]]; then
|
|
SUDO=()
|
|
elif command -v sudo >/dev/null; then
|
|
SUDO=(sudo)
|
|
else
|
|
printf 'BENCH_ERROR\tprepare\troot_or_sudo_required\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
prepare() {
|
|
command -v apt-get >/dev/null || {
|
|
printf 'BENCH_ERROR\tprepare\tapt_get_required\n' >&2
|
|
return 1
|
|
}
|
|
"${SUDO[@]}" apt-get update -qq
|
|
"${SUDO[@]}" env DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
|
|
bash build-essential ca-certificates curl git python3 python3-setuptools unzip xz-utils
|
|
python3 -c 'import setuptools'
|
|
|
|
if [[ "$(node --version 2>/dev/null || true)" != "v${NODE_VERSION}" ]]; then
|
|
local archive="node-v${NODE_VERSION}-linux-x64.tar.xz"
|
|
local prefix="/opt/node-v${NODE_VERSION}-linux-x64"
|
|
curl -fsSL "https://nodejs.org/download/release/v${NODE_VERSION}/${archive}" -o "/tmp/${archive}"
|
|
"${SUDO[@]}" rm -rf "$prefix"
|
|
"${SUDO[@]}" mkdir -p "$prefix"
|
|
"${SUDO[@]}" tar -xJf "/tmp/${archive}" --strip-components=1 -C "$prefix"
|
|
for executable in node npm npx corepack; do
|
|
"${SUDO[@]}" ln -sfn "$prefix/bin/$executable" "/usr/local/bin/$executable"
|
|
done
|
|
fi
|
|
test "$(node --version)" = "v${NODE_VERSION}"
|
|
}
|
|
|
|
download_bun() {
|
|
curl -fsSL \
|
|
"https://github.com/oven-sh/bun/releases/download/bun-v${BUN_VERSION}/bun-linux-x64-baseline.zip" \
|
|
-o "$ROOT/bun.zip"
|
|
}
|
|
|
|
unpack_bun() {
|
|
unzip -q -j "$ROOT/bun.zip" bun-linux-x64-baseline/bun -d "$BUN_INSTALL/bin"
|
|
chmod +x "$BUN_INSTALL/bin/bun"
|
|
}
|
|
|
|
clone_repo() {
|
|
mkdir "$ROOT/repo"
|
|
cd "$ROOT/repo"
|
|
git init -q
|
|
git remote add origin "$REPO_URL"
|
|
git fetch -q --depth=1 origin "$COMMIT"
|
|
git checkout -q --detach FETCH_HEAD
|
|
test "$(git rev-parse HEAD)" = "$COMMIT"
|
|
}
|
|
|
|
install_dependencies() {
|
|
cd "$ROOT/repo"
|
|
bun install
|
|
git diff --exit-code -- bun.lock package.json
|
|
}
|
|
|
|
typecheck() {
|
|
cd "$ROOT/repo"
|
|
bun typecheck
|
|
}
|
|
|
|
disk() {
|
|
du -sx --block-size=1 "$ROOT" | awk '{print $1}'
|
|
}
|
|
|
|
clear_caches() {
|
|
rm -rf "$ROOT"
|
|
"${SUDO[@]}" sync
|
|
if "${SUDO[@]}" sh -c 'echo 3 > /proc/sys/vm/drop_caches' 2>/dev/null; then
|
|
printf 'BENCH_CACHE\tguest_page_cache\tdropped\n'
|
|
else
|
|
printf 'BENCH_CACHE\tguest_page_cache\tunavailable\n'
|
|
fi
|
|
printf 'BENCH_CACHE\tworkspace\tfresh\n'
|
|
printf 'BENCH_CACHE\tbun\tempty\n'
|
|
printf 'BENCH_CACHE\tturbo\tempty\n'
|
|
}
|
|
|
|
cleanup() {
|
|
local status=$?
|
|
if [[ "$KEEP_ROOT" != "true" ]]; then
|
|
rm -rf "$ROOT"
|
|
fi
|
|
exit "$status"
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
total_start="$(timestamp)"
|
|
if ! phase prepare prepare; then
|
|
render_table "❌ prepare"
|
|
exit 1
|
|
fi
|
|
|
|
phase cache_clear clear_caches
|
|
mkdir -p "$ROOT/bun/bin" "$ROOT/home" "$ROOT/bun-cache"
|
|
export HOME="$ROOT/home"
|
|
export BUN_INSTALL="$ROOT/bun"
|
|
export BUN_INSTALL_CACHE_DIR="$ROOT/bun-cache"
|
|
export PATH="$BUN_INSTALL/bin:$PATH"
|
|
export CI=true
|
|
export OPENCODE_DISABLE_SHARE=true
|
|
export TURBO_TELEMETRY_DISABLED=1
|
|
|
|
printf 'BENCH_META\tcommit\t%s\n' "$COMMIT"
|
|
printf 'BENCH_META\tarchitecture\t%s\n' "$(uname -m)"
|
|
printf 'BENCH_META\tkernel\t%s\n' "$(uname -sr)"
|
|
printf 'BENCH_META\tlogical_cpus\t%s\n' "$(getconf _NPROCESSORS_ONLN)"
|
|
printf 'BENCH_META\tcpu_model\t%s\n' "$(awk -F: '/model name/{gsub(/^[ \t]+/, "", $2); print $2; exit}' /proc/cpuinfo)"
|
|
printf 'BENCH_META\tmemory_kib\t%s\n' "$(awk '/MemTotal/{print $2}' /proc/meminfo)"
|
|
|
|
if ! phase bun_download download_bun; then
|
|
render_table "❌ Bun download"
|
|
exit 1
|
|
fi
|
|
if ! phase bun_unpack unpack_bun; then
|
|
render_table "❌ Bun unpack"
|
|
exit 1
|
|
fi
|
|
printf 'BENCH_META\tbun_version\t%s\n' "$(bun --version)"
|
|
printf 'BENCH_META\tnode_version\t%s\n' "$(node --version)"
|
|
|
|
if ! phase clone clone_repo; then
|
|
render_table "❌ clone"
|
|
exit 1
|
|
fi
|
|
printf 'BENCH_DISK\tafter_clone\t%s\n' "$(disk)"
|
|
if ! phase install install_dependencies; then
|
|
render_table "❌ install"
|
|
exit 1
|
|
fi
|
|
printf 'BENCH_DISK\tafter_install\t%s\n' "$(disk)"
|
|
if ! phase typecheck typecheck; then
|
|
render_table "❌ typecheck"
|
|
exit 1
|
|
fi
|
|
printf 'BENCH_DISK\tafter_typecheck\t%s\n' "$(disk)"
|
|
printf 'BENCH_DONE\t%s\n' "$(git -C "$ROOT/repo" rev-parse HEAD)"
|
|
total_end="$(timestamp)"
|
|
printf 'BENCH_PHASE\ttotal\t%s\n' "$(( (total_end - total_start) / 1000000 ))"
|
|
render_table "✅"
|