serve.sh RawHistoryFolder
1#!/usr/bin/env bash
2# SPDX-License-Identifier: AGPL-3.0-or-later
3#
4# Builds ermite from this checkout and starts a throw-away server for the load
5# tests, seeded with repositories whose history spreads over 90 days. The
6# server is pinned to CPUS cores (GOMAXPROCS and taskset), so that the figures
7# say what a small host can do, not what the workstation can.
8#
9# scripts/loadtest/serve.sh # 1 core, http://127.0.0.1:7418
10# CPUS=2 scripts/loadtest/serve.sh
11# scripts/loadtest/serve.sh stop
12set -euo pipefail
13
14ROOT=${LOADTEST_DIR:-${TMPDIR:-/tmp}/ermite-loadtest}
15ADDR=${ADDR:-127.0.0.1:7418}
16CPUS=${CPUS:-1}
17URL=http://$ADDR
18TOKEN=loadtest-admin-token-0123456789abcdefghijklmnop
19
20# stop ends the server and waits for it (it shuts down gracefully), so that
21# its data is never removed under it.
22stop() {
23 [[ -f $ROOT/pid ]] || return 0
24 local pid; pid=$(cat "$ROOT/pid")
25 if kill "$pid" 2>/dev/null; then
26 for _ in $(seq 150); do kill -0 "$pid" 2>/dev/null || break; sleep 0.1; done
27 kill -9 "$pid" 2>/dev/null || true
28 fi
29 rm -f "$ROOT/pid"
30}
31if [[ ${1:-} == stop ]]; then stop; exit 0; fi
32stop
33
34cd "$(git rev-parse --show-toplevel)"
35rm -rf "$ROOT" && mkdir -p "$ROOT/data" "$ROOT/wt"
36GOWORK=off go build -o "$ROOT/ermite" ./cmd/ermite
37BIN=$ROOT/ermite
38
39export ERMITE_DATA_DIR=$ROOT/data ERMITE_PUBLIC_URL=$URL ERMITE_ADDR=$ADDR
40export ERMITE_ADMIN_TOKEN=$TOKEN ERMITE_LOG_FORMAT=console ERMITE_LOG_LEVEL=warn
41export ERMITE_URL=$URL ERMITE_TOKEN=$TOKEN ERMITE_CONFIG=$ROOT/cfg
42
43# The last CPUS of the CPUs this shell may use run the server; run the load
44# generator on the others (see README.md).
45mapfile -t allowed < <(python3 -c 'import os; print(*sorted(os.sched_getaffinity(0)), sep="\n")')
46if ! [[ $CPUS =~ ^[1-9][0-9]*$ ]] || ((CPUS >= ${#allowed[@]})); then
47 echo "CPUS must be between 1 and $((${#allowed[@]} - 1)), got $CPUS" >&2; exit 2
48fi
49server_cpus=$(IFS=,; echo "${allowed[*]: -CPUS}")
50GOMAXPROCS=$CPUS taskset -c "$server_cpus" "$BIN" serve >"$ROOT/log" 2>&1 &
51echo $! >"$ROOT/pid"
52for _ in $(seq 100); do curl -fs "$URL/-/health" >/dev/null && break; sleep 0.1; done
53
54now=$(date +%s)
55seed() { # name visibility description profile
56 local name=$1 vis=$2 desc=$3 prof=$4 d=$ROOT/wt/$1
57 "$BIN" repo create "$name" --visibility "$vis" --description "$desc" >/dev/null
58 mkdir -p "$d" && cd "$d"
59 git init -q -b main . && git config user.email loadtest@example.test && git config user.name Loadtest
60 python3 - "$prof" "$now" >"$ROOT/$name.dates" <<'PY'
61import sys, math, random
62prof, now = sys.argv[1], int(sys.argv[2]); random.seed(prof)
63out = []
64for day in range(89, -1, -1):
65 if prof == 'busy': lam = 6 + 5*math.sin(day/9) + (14 if day < 6 else 0)
66 elif prof == 'bursty': lam = 18 if 40 < day < 48 or 10 < day < 14 else 0.3
67 elif prof == 'sleepy': lam = 3 if day > 60 else 0
68 else: lam = 1.2
69 for _ in range(max(0, int(random.gauss(lam, math.sqrt(lam + 0.1))))):
70 out.append(now - day*86400 - random.randint(0, 80000))
71for t in sorted(out): print(t)
72PY
73 local i=0 subjects=("initial import" "add the parser" "fix an off-by-one error in the tokenizer" "refactor storage layer" "bump dependencies" "document the public API" "tidy up")
74 while read -r t; do
75 i=$((i + 1)); echo $i >f.txt; git add -A
76 GIT_AUTHOR_DATE="@$t" GIT_COMMITTER_DATE="@$t" git commit -qm "${subjects[$((i % 7))]} $i"
77 done <"$ROOT/$name.dates"
78 git tag "v1.$((i / 10)).0"
79 git push -q --tags "http://x:$TOKEN@$ADDR/$name.git" main
80}
81seed alpha public "A small Wayland compositor that spends its frames on your apps" busy
82seed bravo public "Keyboard-driven web browser for tiling window managers" bursty
83seed charlie public "Self-hosted container deployment: push an image, deploy it" steady
84seed delta private "Library that reads terminal output and tracks the screen" sleepy
85"$BIN" repo create echo --visibility public --description "Never pushed" >/dev/null
86
87echo "ermite on $URL, CPU(s) $server_cpus, data in $ROOT (pid $(cat "$ROOT/pid"))"
88echo "admin token: $TOKEN"