mirror of
https://github.com/hanzoai/benchmarks.git
synced 2026-10-30 14:59:11 +00:00
`cd "$(cloud_src)" || exit 1` runs cd on the empty string when the resolver refuses, so a lane that had just printed how to get the source followed it with `cd: null directory`. The path is captured first and checked before anything is entered. Co-authored-by: Hanzo Dev <[email protected]>
91 lines
4.2 KiB
Bash
Executable File
91 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# What it costs to run this yourself.
|
|
#
|
|
# Every other lane measures what the software does. This one measures whether you
|
|
# can have it at all: build the binary from this repo, start it, ask it what it
|
|
# serves, and reach one operation through each door it opens. No account, no
|
|
# image registry, no private module.
|
|
#
|
|
# Re-run it. The numbers in README.md came from this script and nothing else.
|
|
set -euo pipefail
|
|
# The lane runs from the cloud source, which is a different repository now.
|
|
# `cloud_src` finds it or says how to get it (../host.sh).
|
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
. "$HERE/../host.sh"
|
|
SRC="$(cloud_src)" || exit 1
|
|
cd "$SRC"
|
|
|
|
host
|
|
|
|
# A free port, because the point is that this runs beside whatever you already
|
|
# have running.
|
|
P=${P:-18080}; ZP=${ZP:-19653}; HP=${HP:-19090}; AP=${AP:-18081}
|
|
DATA=$(mktemp -d); BIN=$(mktemp -u); PID=""
|
|
# An unset PID must not reach kill: `kill 0` signals the whole process group,
|
|
# which takes down the shell that ran this and leaves no output to read.
|
|
# A CLEANUP THAT CAN FAIL EARLY DOES NOT CLEAN. set -e is in force inside a
|
|
# trap, so `[ -n "$PID" ] && kill ...` returning non-zero — which is what it does
|
|
# whenever PID is empty — aborts the handler before anything is removed. Empty is
|
|
# exactly the early-exit case, a build that did not compile, where the temporary
|
|
# files most want removing. Reproduced in isolation: the marker file survives.
|
|
cleanup() {
|
|
if [ -n "$PID" ]; then kill "$PID" 2>/dev/null || true; fi
|
|
rm -rf "$DATA" "$BIN"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# This repository stands alone, and the point of the lane is that it does. A
|
|
# workspace file in a parent directory would pull in whatever else is checked
|
|
# out beside it and fail on a toolchain none of this needs.
|
|
export GOWORK=off
|
|
|
|
say "private modules required" "$(grep -cE 'hanzo-inc|hanzoai/(iam|kms|commerce)' go.mod || true)"
|
|
|
|
t0=$(python3 -c 'import time;print(time.time())')
|
|
go build -o "$BIN" ./cmd/cloud
|
|
t1=$(python3 -c 'import time;print(time.time())')
|
|
say "build from source" "$(python3 -c "print('%.0f s' % ($t1-$t0))")"
|
|
say "binary" "$(du -h "$BIN" | cut -f1)"
|
|
|
|
# The store refuses to open unencrypted, which is the right default, so a run
|
|
# from source has to say which it wants. This lane asks for the dev path and
|
|
# NOT for a key: a plain `go build` links ordinary SQLite rather than
|
|
# libsqlcipher, so a key here would be a request the binary correctly refuses.
|
|
# See README.md — it is the one row where running it yourself costs something.
|
|
export CLOUD_DEV_UNENCRYPTED=1
|
|
export CLOUD_LISTEN=":$P" CLOUD_ZAP_LISTEN="127.0.0.1:$ZP"
|
|
export CLOUD_HEALTH_LISTEN="127.0.0.1:$HP" CLOUD_ADMIN_LISTEN="127.0.0.1:$AP"
|
|
export CLOUD_DATA_DIR="$DATA"
|
|
|
|
t0=$(python3 -c 'import time;print(time.time())')
|
|
"$BIN" serve >"$DATA/log" 2>&1 & PID=$!
|
|
# Asked of the HEALTH port, not the API port. The API port answers the console's
|
|
# shell for an unrouted path, so a 200 there says the listener is up and nothing
|
|
# about whether the program is ready — measuring against it reads 0.6s where the
|
|
# honest number is half that.
|
|
for _ in $(seq 1 300); do
|
|
curl -s -m 2 "http://127.0.0.1:$HP/healthz" 2>/dev/null | grep -q . && break
|
|
sleep 0.1
|
|
done
|
|
t1=$(python3 -c 'import time;print(time.time())')
|
|
say "boot to a healthy answer" "$(python3 -c "print('%.1f s' % ($t1-$t0))")"
|
|
|
|
curl -s -m 10 "http://127.0.0.1:$P/.well-known/openapi.json" -o "$DATA/api.json"
|
|
ops=$(python3 - "$DATA/api.json" <<'PY'
|
|
import json, sys
|
|
d = json.load(open(sys.argv[1]))
|
|
paths = d.get("paths", {})
|
|
n = sum(1 for p in paths.values() for m in p if m in ("get","post","put","patch","delete"))
|
|
print("%d over %d paths" % (n, len(paths)))
|
|
PY
|
|
)
|
|
say "operations served by default" "$ops"
|
|
|
|
# One operation, every door it opens. A door that does not answer is the row that
|
|
# matters, so each is asked separately rather than counted.
|
|
say "REST" "$(curl -s -o /dev/null -w '%{http_code}' -m 8 "http://127.0.0.1:$P/v1/tasks")"
|
|
say "MCP tools/list" "$(curl -s -m 8 -X POST "http://127.0.0.1:$P/mcp" -H 'Content-Type: application/json' \
|
|
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
|
|
| python3 -c 'import json,sys; print(len(json.load(sys.stdin)["result"]["tools"]), "tools")')"
|
|
say "op-call plane" "$(curl -s -o /dev/null -w '%{http_code}' -m 8 -X POST "http://127.0.0.1:$P/.well-known/zip/op/tasks_list")"
|