Onset: version control where nobody waits and nothing gets lost. The on command, its core and onset-server.
| 6 | # Usage: tests/bench.sh [path/to/target/release] |
| 7 | set -uo pipefail |
| 8 |
| 9 | ROOT=$(cd "$(dirname "$0")/.." && pwd) |
| 10 | BIN=${1:-$ROOT/target/release} |
| 11 | VCS=$BIN/vcs |
| 12 | WORK=$(mktemp -d) |
| 13 | export VCS_SAVER=0 VCS_HOME=$WORK/home VCS_NAME=Bench VCS_EMAIL=bench@example.com |
| 14 | export GIT_AUTHOR_NAME=Bench GIT_AUTHOR_EMAIL=bench@example.com GIT_COMMITTER_NAME=Bench GIT_COMMITTER_EMAIL=bench@example.com |
| 15 | PORT=$((20000 + RANDOM % 20000)) |
| 16 | HOST="127.0.0.1:$PORT" |
| 17 | SERVER_PID= |
| 18 | cleanup() { |
| 19 | [ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null |
| 20 | rm -rf "$WORK" |
| 21 | } |
| 22 | trap cleanup EXIT |
| 23 | cd "$WORK" |
| 24 | g() { git -c init.defaultBranch=main -c commit.gpgsign=false -c advice.detachedHead=false "$@"; } |
| 25 | now() { python3 -c 'import time; print(time.time())'; } |
| 26 | since() { python3 -c "import time; print(f'{time.time() - $1:.2f}')"; } |
| 27 | best() { # fastest of 5 runs, in ms |
| 28 | python3 - "$@" <<'EOF' |
| 29 | import subprocess, sys, time |
| 30 | best = 1e9 |
| 31 | for _ in range(5): |
| 32 | t = time.time(); subprocess.run(sys.argv[1:], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL); best = min(best, time.time() - t) |
| 33 | print(f"{best * 1000:.0f}") |
| 34 | EOF |
| 35 | } |
| 36 | files() { # folder, count |
| 37 | python3 - "$1" "$2" <<'EOF' |
| 38 | import os, sys |
| 39 | root, n = sys.argv[1], int(sys.argv[2]) |
| 40 | for i in range(n): |
| 41 | d = os.path.join(root, "src", f"m{i // 20:04d}") |
| 42 | os.makedirs(d, exist_ok=True) |
| 43 | with open(os.path.join(d, f"f{i:05d}.ts"), "w") as f: |
| 44 | f.write(f"export const v{i} = {i};\n" * 30) |
| 45 | EOF |
| 46 | } |
| 47 | row() { printf '%-52s %12s %12s\n' "$1" "$2" "$3"; } |
| 48 |
| 49 | "$BIN/vcs-server" user add bench --name Bench --email bench@example.com --data "$WORK/server" > token |
| 50 | "$BIN/vcs-server" serve --data "$WORK/server" --listen "$HOST" --threads 32 2>/dev/null & |
| 51 | SERVER_PID=$! |
| 52 | for _ in $(seq 50); do curl -s "http://$HOST/.well-known/vcs.json" >/dev/null && break; sleep 0.1; done |
| 53 | "$VCS" login "$HOST" --token "$(cat token)" >/dev/null |
| 54 |
| 55 | echo "vcs $("$VCS" --version | cut -d' ' -f2) vs $(git --version) ($(nproc) cores, $(uname -s))" |
| 56 | echo |
| 57 | row "" "git" "vcs" |
| 58 |
| 59 | # The same 20,000-file project in both. |
| 60 | mkdir gseed && files gseed 20000 && (cd gseed && g init -q && g add -A && g commit -qm "20k files") |
| 61 | g clone -q --bare gseed big.git |
| 62 | "$VCS" init vseed >/dev/null && files vseed 20000 && "$VCS" -C vseed land -m "20k files" >/dev/null |
| 63 | "$VCS" -C vseed publish "$HOST/bench/big" >/dev/null |
| 64 | g clone -q big.git gbig |
| 65 | "$VCS" get "$HOST/bench/big" vbig >/dev/null |
| 66 | sleep 1.5 |
| 67 |
| 68 | row "status, 20,000 files, nothing changed (ms)" "$(best git -C gbig status)" "$(best "$VCS" -C vbig status)" |
| 69 | printf 'edit\n' >> gbig/src/m0500/f10000.ts |
| 70 | printf 'edit\n' >> vbig/src/m0500/f10000.ts |
| 71 | row "status, 20,000 files, one file changed (ms)" "$(best git -C gbig status)" "$(best "$VCS" -C vbig status)" |
| 72 | git -C gbig checkout -q -- . && "$VCS" -C vbig restore src/m0500/f10000.ts >/dev/null |
| 73 |
| 74 | t=$(now); g clone -q --no-local "file://$WORK/big.git" gfresh; tg=$(since "$t") |
| 75 | t=$(now); VCS_HOME=$WORK/fresh "$VCS" login "$HOST" --token "$(cat token)" >/dev/null; VCS_HOME=$WORK/fresh "$VCS" get "$HOST/bench/big" vfresh >/dev/null; tv=$(since "$t") |
| 76 | row "first copy on a new machine, 20,000 files (s)" "$tg" "$tv" |
| 77 | t=$(now); git -C gbig worktree add -q ../gwt >/dev/null 2>&1; tg=$(since "$t") |
| 78 | t=$(now); "$VCS" get "$HOST/bench/big" vbig2 >/dev/null; tv=$(since "$t") |
| 79 | row "second working copy, same machine (s)" "$tg" "$tv" |
| 80 |
| 81 | # One small change, start to finish, ten times: commit + push vs land. |
| 82 | gl=() |
| 83 | vl=() |
| 84 | for i in $(seq 1 10); do |
| 85 | printf 'change %s\n' "$i" >> gbig/README.md |
| 86 | t=$(now); (cd gbig && g add -A && g commit -qm "Change $i" && g push -q origin HEAD:main); gl+=("$(since "$t")") |
| 87 | printf 'change %s\n' "$i" >> vbig/README.md |
| 88 | t=$(now); "$VCS" -C vbig land -m "Change $i" >/dev/null; vl+=("$(since "$t")") |
| 89 | done |
| 90 | med() { printf '%s\n' "$@" | sort -n | sed -n "$(( ($# + 1) / 2 ))p"; } |
| 91 | row "one change: commit + push vs land, median (s)" "$(med "${gl[@]}")" "$(med "${vl[@]}")" |
| 92 |
| 93 | # Many agents, one branch, at once. Each makes one change to its own file. |
| 94 | race() { # agents |
| 95 | local n=$1 |
| 96 | rm -rf race && mkdir race && cd race |
| 97 | mkdir seed && files seed 1500 && (cd seed && g init -q && g add -A && g commit -qm base) |
| 98 | g clone -q --bare seed server.git |
| 99 | for i in $(seq 1 "$n"); do g clone -q server.git "g$i" && printf '%s\n' "$i" > "g$i/agent-$i.txt" && (cd "g$i" && g add -A && g commit -qm "Agent $i"); done |
| 100 | "$VCS" init vseed >/dev/null && files vseed 1500 && "$VCS" -C vseed land -m base >/dev/null && "$VCS" -C vseed publish "$HOST/bench/race$n" >/dev/null |
| 101 | for i in $(seq 1 "$n"); do "$VCS" get "$HOST/bench/race$n" "v$i" >/dev/null && printf '%s\n' "$i" > "v$i/agent-$i.txt"; done |
| 102 | sync |
| 103 | local t pids=() |
| 104 | t=$(now) |
| 105 | for i in $(seq 1 "$n"); do |
| 106 | (cd "g$i"; tries=0; until g push -q origin HEAD:main 2>/dev/null; do tries=$((tries + 1)); g pull -q --rebase origin main 2>/dev/null; done; echo "$tries" > "../tries$i") & |
| 107 | pids+=($!) |
| 108 | done |
| 109 | wait "${pids[@]}" |
| 110 | local tg refused |
| 111 | tg=$(since "$t") |
| 112 | refused=$(cat tries* | python3 -c "import sys; print(sum(int(l) for l in sys.stdin))") |
| 113 | pids=() |
| 114 | t=$(now) |
| 115 | for i in $(seq 1 "$n"); do ("$VCS" -C "v$i" land -m "Agent $i" >/dev/null 2>&1; echo $? > "vcode$i") & pids+=($!); done |
| 116 | wait "${pids[@]}" |
| 117 | local tv landed |
| 118 | tv=$(since "$t") |
| 119 | landed=$(grep -l '^0$' vcode* | wc -l | tr -d ' ') |
| 120 | row "$n agents land one change each on one branch (s)" "$tg" "$tv" |
| 121 | row " refused pushes / changes that didn't land" "$refused" "$((n - landed))" |
| 122 | cd "$WORK" |
| 123 | } |
| 124 | race 8 |
| 125 | race 32 |
| 126 | race 64 |
| 127 |