|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# Build a native Go benchmark binary from Clojure sources via gloat, |
| 4 | +# then run it. Usage: ./bench2.sh [glojure-commit] |
| 5 | +# Assumes deps already bootstrapped (run make build once). |
| 6 | + |
| 7 | +set -euo pipefail |
| 8 | + |
| 9 | +ROOT=$(cd "$(dirname "$0")/.." && pwd) |
| 10 | +GLOJURE=$ROOT/../glojure |
| 11 | +COMMIT=${1:-gloat} |
| 12 | + |
| 13 | +echo "=== 0. Clone glojure @ $COMMIT ===" |
| 14 | +GLOJURE_BUILD=/tmp/glojure/$COMMIT |
| 15 | +rm -fr "$GLOJURE_BUILD" |
| 16 | +git clone -q "$GLOJURE/.git" "$GLOJURE_BUILD" |
| 17 | +git -C "$GLOJURE_BUILD" checkout -q "$COMMIT" |
| 18 | + |
| 19 | +# Auto-detect local root and gloat installation |
| 20 | +GLOAT_HOME=$HOME/.local/share/gloat |
| 21 | +if [[ -d /tmp/yamlstar-local/go-1.26.0 ]]; then |
| 22 | + LOCAL=/tmp/yamlstar-local |
| 23 | + GLOAT_DIR=$LOCAL/cache/gloat-main |
| 24 | +elif [[ -d $ROOT/.cache/.local/go-1.26.0 ]]; then |
| 25 | + LOCAL=$ROOT/.cache/.local |
| 26 | + GLOAT_DIR=$LOCAL/cache/gloat-main |
| 27 | +elif [[ -d $GLOAT_HOME/.cache/.local/go-1.26.0 ]]; then |
| 28 | + LOCAL=$GLOAT_HOME/.cache/.local |
| 29 | + GLOAT_DIR=$GLOAT_HOME |
| 30 | +else |
| 31 | + echo "ERROR: Cannot find Go installation" >&2 |
| 32 | + exit 1 |
| 33 | +fi |
| 34 | + |
| 35 | +GO=$LOCAL/go-1.26.0/bin/go |
| 36 | +GLOAT=$GLOAT_DIR/bin/gloat |
| 37 | +GLJ=$LOCAL/bin/glj |
| 38 | + |
| 39 | +# Find gloat's own glj path (may differ from $GLJ). |
| 40 | +# Always query from GLOAT_HOME which has the Makefile with gloat-vars. |
| 41 | +GLOAT_GLJ=$(cd "$GLOAT_HOME" && make --quiet --no-print-directory gloat-vars 2>/dev/null \ |
| 42 | + | grep ':GLJ ' | sed 's/.*:GLJ "\(.*\)"/\1/') |
| 43 | + |
| 44 | +BUILD_DIR=/tmp/yamlstar-bench |
| 45 | +BINARY=$BUILD_DIR/bench |
| 46 | + |
| 47 | +SRCS=( |
| 48 | + $ROOT/core/src/yamlstar/parser/prelude.clj |
| 49 | + $ROOT/core/src/yamlstar/parser/parser.clj |
| 50 | + $ROOT/core/src/yamlstar/parser/receiver.clj |
| 51 | + $ROOT/core/src/yamlstar/parser/grammar.clj |
| 52 | + $ROOT/core/src/yamlstar/parser.clj |
| 53 | + $ROOT/core/src/yamlstar/composer.clj |
| 54 | + $ROOT/core/src/yamlstar/resolver.clj |
| 55 | + $ROOT/core/src/yamlstar/constructor.clj |
| 56 | + $ROOT/core/src/yamlstar/core.clj |
| 57 | + $ROOT/bench/bench2.clj |
| 58 | +) |
| 59 | + |
| 60 | +# Patch gloat's template go.mod to use the cloned glojure. |
| 61 | +# The template may not have a replace line, so append one if missing. |
| 62 | +for gomod in "$GLOAT_DIR/template/go.mod" "$GLOAT_DIR/ys/pkg/go.mod"; do |
| 63 | + if grep -q 'replace github.com/gloathub/glojure =>' "$gomod"; then |
| 64 | + sed -i "s|replace github.com/gloathub/glojure => .*|replace github.com/gloathub/glojure => $GLOJURE_BUILD|" "$gomod" |
| 65 | + else |
| 66 | + echo "replace github.com/gloathub/glojure => $GLOJURE_BUILD" >> "$gomod" |
| 67 | + fi |
| 68 | +done |
| 69 | + |
| 70 | +echo |
| 71 | +echo "=== 1. Build glj from $COMMIT ===" |
| 72 | +time (cd "$GLOJURE_BUILD" && $GO build -o "$GLJ" ./cmd/glj) |
| 73 | +# Copy to gloat's glj path if different, so gloat uses our build |
| 74 | +if [[ -n "$GLOAT_GLJ" && "$GLOAT_GLJ" != "$GLJ" ]]; then |
| 75 | + echo "Copying glj to gloat path: $GLOAT_GLJ" |
| 76 | + cp "$GLJ" "$GLOAT_GLJ" |
| 77 | + touch "$GLOAT_GLJ" |
| 78 | +fi |
| 79 | +touch "$GLJ" |
| 80 | + |
| 81 | +echo |
| 82 | +echo "=== 2. Compile to Go project ===" |
| 83 | +time (</dev/null env -u GOROOT "$GLOAT" "${SRCS[@]}" -o "$BUILD_DIR/" --force) |
| 84 | + |
| 85 | +# Patch the generated go.mod to use the cloned glojure. |
| 86 | +if grep -q 'replace github.com/gloathub/glojure =>' "$BUILD_DIR/go.mod"; then |
| 87 | + sed -i "s|replace github.com/gloathub/glojure => .*|replace github.com/gloathub/glojure => $GLOJURE_BUILD|" \ |
| 88 | + "$BUILD_DIR/go.mod" |
| 89 | +else |
| 90 | + echo "replace github.com/gloathub/glojure => $GLOJURE_BUILD" >> "$BUILD_DIR/go.mod" |
| 91 | +fi |
| 92 | + |
| 93 | +echo |
| 94 | +echo "=== 3. Build binary ===" |
| 95 | +# Patch main.go to call bench2/-main instead of whatever gloat picked |
| 96 | +sed -i 's|Var("[^"]*", "-main")|Var("bench2", "-main")|' "$BUILD_DIR/main.go" |
| 97 | +sed -i 's|FindOrCreateNamespace(lang.NewSymbol("[^"]*"))|FindOrCreateNamespace(lang.NewSymbol("bench2"))|' "$BUILD_DIR/main.go" |
| 98 | +time (cd "$BUILD_DIR" && $GO mod tidy && $GO build -o "$BINARY" .) |
| 99 | + |
| 100 | +echo |
| 101 | +echo "=== 4. Benchmark ===" |
| 102 | +MAX_LOAD=${MAX_LOAD:-2.0} |
| 103 | +while true; do |
| 104 | + load=$(awk '{print $1}' /proc/loadavg) |
| 105 | + if awk "BEGIN{exit !($load < $MAX_LOAD)}"; then |
| 106 | + break |
| 107 | + fi |
| 108 | + printf "Load average %.2f >= %.2f, waiting...\r" "$load" "$MAX_LOAD" |
| 109 | + sleep 5 |
| 110 | +done |
| 111 | +echo "Load average $(awk '{print $1}' /proc/loadavg) — starting benchmark" |
| 112 | +"$BINARY" |
| 113 | +echo "Load average $(awk '{print $1}' /proc/loadavg) — benchmark complete" |
0 commit comments