ops: castopod/bonfire notes; amount-ladder bench
This commit is contained in:
parent
acff09d130
commit
84388ae6a9
9 changed files with 749 additions and 3 deletions
375
benchmarks/amount-ladder/run.sh
Executable file
375
benchmarks/amount-ladder/run.sh
Executable file
|
|
@ -0,0 +1,375 @@
|
|||
#!/bin/bash
|
||||
# Amount-ladder benchmark — drive from the local machine, measure on koopa (inside containers).
|
||||
# See README.md in this directory.
|
||||
set -eu
|
||||
|
||||
BENCH_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
ROOT=$(cd "$BENCH_DIR/../.." && pwd)
|
||||
SECRETS="${SECRETS_DIR:-}"
|
||||
if [ -z "$SECRETS" ]; then
|
||||
if [ -d "$ROOT/../koopa-admin-secrets" ]; then
|
||||
SECRETS=$(cd "$ROOT/../koopa-admin-secrets" && pwd)
|
||||
else
|
||||
SECRETS="$ROOT/../koopa-admin-secrets"
|
||||
fi
|
||||
fi
|
||||
|
||||
SCRATCH="${ROOT}/.tmp/amount-bench-$(date -u +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$SCRATCH"
|
||||
chmod 700 "$SCRATCH"
|
||||
|
||||
MONO="${MONO:-/Users/newkamek/src/taler/taler-typescript-core/packages/taler-wallet-cli/bin/taler-wallet-cli.mjs}"
|
||||
WDB="$SCRATCH/wallet.sqlite3"
|
||||
EX="${EXCHANGE_URL:-https://exchange.hacktivism.ch/}"
|
||||
KOOPA="${KOOPA_HOST:-koopa}"
|
||||
INST="${MERCHANT_INSTANCE:-goa-demo-cp4zqk}"
|
||||
TPL="${TEMPLATE_ID:-goa-free}"
|
||||
MER_HOST="${MER_HOST:-taler.hacktivism.ch}"
|
||||
FAT_USER="${FAT_USER:-bench-fat}"
|
||||
# ~20 payments: small → medium → large (atomic/tiny through multi-kilo)
|
||||
# Override: AMOUNTS='GOA:1 GOA:10' ./run.sh
|
||||
AMOUNTS="${AMOUNTS:-GOA:0.000001 GOA:0.00001 GOA:0.0001 GOA:0.001 GOA:0.01 GOA:0.05 GOA:0.1 GOA:0.5 GOA:1 GOA:2 GOA:5 GOA:10 GOA:25 GOA:50 GOA:100 GOA:250 GOA:500 GOA:1000 GOA:2500 GOA:5000}"
|
||||
# sum of default ladder ≈ GOA:9433 → withdraw headroom for multi-coin + fees
|
||||
WITHDRAW_AMT="${WITHDRAW_AMT:-GOA:50000}"
|
||||
CREDIT_AMT="${CREDIT_AMT:-GOA:200000}"
|
||||
|
||||
BANK_ADMIN_PW_FILE="${BANK_ADMIN_PW_FILE:-$SECRETS/koopa/host-root/taler-bank/bank-admin-password.txt}"
|
||||
BANK_FAT_PW_FILE="${BANK_FAT_PW_FILE:-$SECRETS/koopa/host-root/taler-bank/bank-bench-fat-password.txt}"
|
||||
MER_PW_FILE="${MER_PW_FILE:-$SECRETS/koopa/host-root/taler-merchant/merchant-${INST}-password.txt}"
|
||||
|
||||
wcli() { node "$MONO" --wallet-db="$WDB" --no-throttle --skip-defaults "$@"; }
|
||||
log() { echo "$(date -u +%H:%M:%S) $*" | tee -a "$SCRATCH/run.log"; }
|
||||
now() { python3 -c 'import time;print(time.time())'; }
|
||||
die() { log "FAIL $*"; exit 1; }
|
||||
|
||||
[ -f "$MONO" ] || die "wallet cli missing: $MONO"
|
||||
[ -f "$BANK_ADMIN_PW_FILE" ] || die "missing $BANK_ADMIN_PW_FILE"
|
||||
[ -f "$MER_PW_FILE" ] || die "missing $MER_PW_FILE"
|
||||
|
||||
ADMIN_PW=$(tr -d '\n' <"$BANK_ADMIN_PW_FILE")
|
||||
MER_PW=$(tr -d '\n' <"$MER_PW_FILE")
|
||||
if [ -f "$BANK_FAT_PW_FILE" ]; then
|
||||
FAT_PW=$(tr -d '\n' <"$BANK_FAT_PW_FILE")
|
||||
else
|
||||
FAT_PW=$(openssl rand -hex 12)
|
||||
mkdir -p "$(dirname "$BANK_FAT_PW_FILE")"
|
||||
printf '%s\n' "$FAT_PW" >"$BANK_FAT_PW_FILE"
|
||||
chmod 600 "$BANK_FAT_PW_FILE"
|
||||
log "generated fat password -> $BANK_FAT_PW_FILE (secrets repo)"
|
||||
fi
|
||||
|
||||
# --- remote: run short script as hernani, capture stdout ---
|
||||
run_koopa() {
|
||||
local id="$1"
|
||||
shift
|
||||
local script_local="$SCRATCH/remote-$id.sh"
|
||||
local mark="BENCH_${id}_OK"
|
||||
{
|
||||
echo '#!/bin/bash'
|
||||
echo 'set +e'
|
||||
printf '%s\n' "$@"
|
||||
echo "echo $mark"
|
||||
} >"$script_local"
|
||||
scp -o BatchMode=yes -q "$script_local" "${KOOPA}:/tmp/bench-run-$id.sh"
|
||||
ssh -o BatchMode=yes "$KOOPA" "bash /tmp/bench-run-$id.sh; rm -f /tmp/bench-run-$id.sh" \
|
||||
>"$SCRATCH/koopa-$id.out" 2>&1 || true
|
||||
if ! grep -q "$mark" "$SCRATCH/koopa-$id.out" 2>/dev/null; then
|
||||
log "WARN run_koopa $id incomplete (see koopa-$id.out)"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Measure **inside** containers (and host loadavg)
|
||||
sample_load() {
|
||||
local tag="$1"
|
||||
scp -o BatchMode=yes -q "$BENCH_DIR/sample-load-inside.sh" "${KOOPA}:/tmp/sample-load-inside.sh"
|
||||
ssh -o BatchMode=yes "$KOOPA" "bash /tmp/sample-load-inside.sh $(printf %q "$tag"); rm -f /tmp/sample-load-inside.sh" \
|
||||
>"$SCRATCH/koopa-load-$tag.out" 2>&1 || true
|
||||
}
|
||||
|
||||
log "scratch=$SCRATCH"
|
||||
log "AMOUNTS=$AMOUNTS"
|
||||
|
||||
# --- preflight (external, public HTTPS) ---
|
||||
for url in \
|
||||
"https://taler.hacktivism.ch/config" \
|
||||
"https://exchange.hacktivism.ch/keys" \
|
||||
"https://taler.hacktivism.ch/instances/${INST}/templates/${TPL}"
|
||||
do
|
||||
code=$(curl -sk -o /dev/null -w '%{http_code}' -m 10 "$url" || echo err)
|
||||
log "preflight $url -> $code"
|
||||
[ "$code" = "200" ] || die "preflight failed $url"
|
||||
done
|
||||
|
||||
# --- bank setup on koopa (API localhost, orchestrated from the local machine) ---
|
||||
log "=== bank setup $FAT_USER credit=$CREDIT_AMT withdraw=$WITHDRAW_AMT ==="
|
||||
{
|
||||
echo '#!/bin/bash'
|
||||
echo 'set -euo pipefail'
|
||||
echo "export ADMIN_PW=$(printf %q "$ADMIN_PW")"
|
||||
echo "export FAT_PW=$(printf %q "$FAT_PW")"
|
||||
echo "export FAT_USER=$(printf %q "$FAT_USER")"
|
||||
echo "export CREDIT_AMT=$(printf %q "$CREDIT_AMT")"
|
||||
echo "export WITHDRAW_AMT=$(printf %q "$WITHDRAW_AMT")"
|
||||
cat <<'EOS'
|
||||
BANK=http://127.0.0.1:9012
|
||||
AT=$(curl -sS -u "admin:${ADMIN_PW}" -H "Content-Type: application/json" -d '{"scope":"readwrite"}' \
|
||||
"$BANK/accounts/admin/token" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
|
||||
echo admin_tok_len=${#AT}
|
||||
curl -sS -o /tmp/acc.json -w "create:%{http_code}\n" -X POST -H "Authorization: Bearer $AT" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"username\":\"${FAT_USER}\",\"password\":\"${FAT_PW}\",\"name\":\"Bench Fat\",\"is_public\":false,\"is_taler_exchange\":false,\"debit_threshold\":\"GOA:0\"}" \
|
||||
"$BANK/accounts" || true
|
||||
echo create_body=$(head -c 160 /tmp/acc.json)
|
||||
python3 - <<'PY'
|
||||
import json, os
|
||||
A="0123456789ABCDEFGHJKMNPQRSTVWXYZ"
|
||||
def c32(b):
|
||||
v=bits=0; o=[]
|
||||
for x in b:
|
||||
v=(v<<8)|x; bits+=8
|
||||
while bits>=5:
|
||||
bits-=5; o.append(A[(v>>bits)&31])
|
||||
if bits: o.append(A[(v<<(5-bits))&31])
|
||||
return "".join(o)
|
||||
uid=c32(os.urandom(32))
|
||||
user=os.environ["FAT_USER"]
|
||||
amt=os.environ["CREDIT_AMT"]
|
||||
payto=f"payto://x-taler-bank/bank.hacktivism.ch/{user}?receiver-name={user}&message=bench-credit"
|
||||
json.dump({"payto_uri":payto,"amount":amt,"request_uid":uid}, open("/tmp/tx.json","w"))
|
||||
print("credit", amt, "->", user, "uid", uid)
|
||||
PY
|
||||
curl -sS -o /tmp/cred.json -w "credit:%{http_code}\n" -X POST -H "Authorization: Bearer $AT" \
|
||||
-H "Content-Type: application/json" -d @/tmp/tx.json "$BANK/accounts/admin/transactions"
|
||||
echo credit_body=$(head -c 200 /tmp/cred.json)
|
||||
BT=$(curl -sS -u "${FAT_USER}:${FAT_PW}" -H "Content-Type: application/json" -d '{"scope":"readwrite"}' \
|
||||
"$BANK/accounts/${FAT_USER}/token" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
|
||||
echo fat_tok_len=${#BT}
|
||||
curl -sS -H "Authorization: Bearer $BT" "$BANK/accounts/${FAT_USER}" -o /tmp/fatbal.json
|
||||
echo fat_account=$(head -c 280 /tmp/fatbal.json)
|
||||
curl -sS -o /tmp/wd.json -w "wd:%{http_code}\n" -X POST -H "Authorization: Bearer $BT" \
|
||||
-H "Content-Type: application/json" -d "{\"amount\":\"${WITHDRAW_AMT}\"}" \
|
||||
"$BANK/accounts/${FAT_USER}/withdrawals"
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
d=json.load(open("/tmp/wd.json"))
|
||||
print("wd_keys", list(d.keys())[:20])
|
||||
uri=d.get("taler_withdraw_uri") or d.get("withdrawal_uri") or ""
|
||||
wid=d.get("withdrawal_id") or d.get("id") or ""
|
||||
if not uri:
|
||||
for v in d.values():
|
||||
if isinstance(v, str) and v.startswith("taler"):
|
||||
uri=v
|
||||
open("/tmp/bench-wuri.txt","w").write(uri)
|
||||
open("/tmp/bench-wid.txt","w").write(wid)
|
||||
print("WURI", uri)
|
||||
print("WID", wid)
|
||||
assert uri and wid, d
|
||||
PY
|
||||
# cleanup setup temps on host (not durable)
|
||||
rm -f /tmp/acc.json /tmp/tx.json /tmp/cred.json /tmp/fatbal.json /tmp/wd.json
|
||||
echo BENCH_banksetup_OK
|
||||
EOS
|
||||
} >"$SCRATCH/remote-banksetup.sh"
|
||||
scp -o BatchMode=yes -q "$SCRATCH/remote-banksetup.sh" "${KOOPA}:/tmp/bench-run-banksetup.sh"
|
||||
ssh -o BatchMode=yes "$KOOPA" 'bash /tmp/bench-run-banksetup.sh; rm -f /tmp/bench-run-banksetup.sh' \
|
||||
| tee "$SCRATCH/koopa-banksetup.out"
|
||||
grep -q BENCH_banksetup_OK "$SCRATCH/koopa-banksetup.out" || die "bank setup failed"
|
||||
scp -o BatchMode=yes -q "${KOOPA}:/tmp/bench-wuri.txt" "${KOOPA}:/tmp/bench-wid.txt" "$SCRATCH/"
|
||||
ssh -o BatchMode=yes "$KOOPA" 'rm -f /tmp/bench-wuri.txt /tmp/bench-wid.txt' || true
|
||||
WURI=$(tr -d '\n' <"$SCRATCH/bench-wuri.txt")
|
||||
WID=$(tr -d '\n' <"$SCRATCH/bench-wid.txt")
|
||||
[ -n "$WURI" ] || die "missing withdraw URI"
|
||||
log "WURI=$WURI WID=$WID"
|
||||
|
||||
log "=== load baseline (internal) ==="
|
||||
sample_load baseline
|
||||
|
||||
log "=== wallet: exchange + withdraw (external) ==="
|
||||
wcli exchanges add "$EX" 2>&1 | tee "$SCRATCH/ex-add.out" || true
|
||||
wcli exchanges update "$EX" 2>&1 | tee "$SCRATCH/ex-upd.out" || true
|
||||
wcli exchanges tos "$EX" 2>&1 | tee "$SCRATCH/ex-tos.out" || true
|
||||
wcli exchanges accept-tos "$EX" 2>&1 | tee "$SCRATCH/ex-accept.out" || true
|
||||
|
||||
TW0=$(now)
|
||||
# 1) Wallet selects exchange (status → selected). Must happen BEFORE bank confirm.
|
||||
wcli withdraw accept-uri --exchange "$EX" "$WURI" 2>&1 | tee "$SCRATCH/wd-accept.out" || true
|
||||
|
||||
# 2) Wait until bank sees selection, then confirm once (libeufin rejects confirm if still unselected).
|
||||
log "=== bank: wait selected → confirm ==="
|
||||
run_koopa wdconfirm \
|
||||
"export FAT_USER=$(printf %q "$FAT_USER")" \
|
||||
"export FAT_PW=$(printf %q "$FAT_PW")" \
|
||||
"export WID=$(printf %q "$WID")" \
|
||||
'BANK=http://127.0.0.1:9012' \
|
||||
'BT=$(curl -sS -u "${FAT_USER}:${FAT_PW}" -H "Content-Type: application/json" -d "{\"scope\":\"readwrite\"}" "$BANK/accounts/${FAT_USER}/token" | python3 -c "import sys,json;print(json.load(sys.stdin).get(\"access_token\",\"\"))")' \
|
||||
'echo WID=$WID tok_len=${#BT}' \
|
||||
'st=""' \
|
||||
'for i in $(seq 1 60); do
|
||||
curl -sS "$BANK/taler-integration/withdrawal-operation/${WID}" -o /tmp/wdst.json || true
|
||||
st=$(python3 -c "import json;print(json.load(open(\"/tmp/wdst.json\")).get(\"status\",\"\"))" 2>/dev/null || true)
|
||||
echo "wait_select #$i status=$st"
|
||||
case "$st" in selected|confirmed) break ;; esac
|
||||
sleep 1
|
||||
done' \
|
||||
'case "$st" in
|
||||
selected)
|
||||
echo confirming...
|
||||
curl -sS -o /tmp/wdconf.out -w "confirm_http:%{http_code}\n" -X POST \
|
||||
-H "Authorization: Bearer $BT" -H "Content-Type: application/json" -d "{}" \
|
||||
"$BANK/accounts/${FAT_USER}/withdrawals/${WID}/confirm"
|
||||
head -c 120 /tmp/wdconf.out; echo
|
||||
;;
|
||||
confirmed) echo already_confirmed ;;
|
||||
*) echo "WARN never selected (last=$st)" ;;
|
||||
esac' \
|
||||
'for i in $(seq 1 30); do
|
||||
curl -sS "$BANK/taler-integration/withdrawal-operation/${WID}" -o /tmp/wdst.json || true
|
||||
python3 -c "import json;d=json.load(open(\"/tmp/wdst.json\"));print(\"post\",d.get(\"status\"),\"transfer\",d.get(\"transfer_done\"))"
|
||||
st=$(python3 -c "import json;print(json.load(open(\"/tmp/wdst.json\")).get(\"status\",\"\"))" 2>/dev/null || true)
|
||||
td=$(python3 -c "import json;print(json.load(open(\"/tmp/wdst.json\")).get(\"transfer_done\"))" 2>/dev/null || true)
|
||||
case "$st" in confirmed) break ;; esac
|
||||
[ "$td" = "True" ] || [ "$td" = "true" ] && break
|
||||
sleep 1
|
||||
done
|
||||
rm -f /tmp/wdst.json /tmp/wdconf.out' || true
|
||||
|
||||
# 3) Wallet finishes planchets (may take minutes for large withdraws)
|
||||
log "=== wallet: run-until-done after confirm ==="
|
||||
for round in $(seq 1 30); do
|
||||
log "withdraw run-until-done round $round"
|
||||
# timeout each round so we do not hang forever on long-poll
|
||||
set +e
|
||||
# 120s max per round
|
||||
perl -e 'alarm shift; exec @ARGV' 120 \
|
||||
node "$MONO" --wallet-db="$WDB" --no-throttle --skip-defaults run-until-done \
|
||||
2>&1 | tee -a "$SCRATCH/wd-rud.out"
|
||||
set -e
|
||||
wcli balance 2>&1 | tee "$SCRATCH/bal-wd-$round.out"
|
||||
if python3 - "$SCRATCH/bal-wd-$round.out" <<'PY'
|
||||
import re,sys
|
||||
t=open(sys.argv[1]).read()
|
||||
vals=[float(x) for x in re.findall(r"GOA:([0-9.]+)", t)]
|
||||
sys.exit(0 if vals and max(vals) >= 100 else 1)
|
||||
PY
|
||||
then
|
||||
log "withdraw OK"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
TW1=$(now)
|
||||
python3 -c "print('withdraw_wall_s', round(float('$TW1')-float('$TW0'), 3))" | tee "$SCRATCH/withdraw-time.txt"
|
||||
wcli balance 2>&1 | tee "$SCRATCH/balance-before-pays.out"
|
||||
sample_load after-withdraw
|
||||
|
||||
CSV="$SCRATCH/payments.csv"
|
||||
echo "idx,amount,handle_s,rud_s,total_s,status,order_id,loadavg,notes" >"$CSV"
|
||||
|
||||
idx=0
|
||||
for AMT in $AMOUNTS; do
|
||||
idx=$((idx + 1))
|
||||
# no trailing slash; amount only (template has fixed summary)
|
||||
URI="taler://pay-template/${MER_HOST}/instances/${INST}/${TPL}?amount=${AMT}"
|
||||
echo "$URI" >"$SCRATCH/uri-$idx.txt"
|
||||
log "=== pay #$idx $AMT ==="
|
||||
log "uri=$URI"
|
||||
|
||||
load_before=$(ssh -o BatchMode=yes "$KOOPA" 'cut -d" " -f1 /proc/loadavg' 2>/dev/null || echo "?")
|
||||
sample_load "pay$idx" &
|
||||
SPID=$!
|
||||
|
||||
T0=$(now)
|
||||
set +e
|
||||
wcli handle-uri --yes --non-interactive "$URI" 2>&1 | tee "$SCRATCH/pay-$idx-handle.out"
|
||||
T1=$(now)
|
||||
wcli run-until-done 2>&1 | tee "$SCRATCH/pay-$idx-rud.out"
|
||||
T2=$(now)
|
||||
set -e
|
||||
|
||||
handle_s=$(python3 -c "print(round(float('$T1')-float('$T0'),3))")
|
||||
rud_s=$(python3 -c "print(round(float('$T2')-float('$T1'),3))")
|
||||
total_s=$(python3 -c "print(round(float('$T2')-float('$T0'),3))")
|
||||
wait "$SPID" 2>/dev/null || true
|
||||
load_after=$(ssh -o BatchMode=yes "$KOOPA" 'cut -d" " -f1 /proc/loadavg' 2>/dev/null || echo "?")
|
||||
|
||||
run_koopa "ord$idx" \
|
||||
"export MPW=$(printf %q "$MER_PW")" \
|
||||
"export INST=$(printf %q "$INST")" \
|
||||
"export AMT=$(printf %q "$AMT")" \
|
||||
'AUTH="Authorization: Bearer secret-token:${MPW}"' \
|
||||
'curl -sk -H "$AUTH" "https://127.0.0.1:9010/instances/${INST}/private/orders?paid=YES&delta=-30" -o /tmp/ol.json' \
|
||||
'python3 - <<PY
|
||||
import json, os
|
||||
d=json.load(open("/tmp/ol.json"))
|
||||
want=os.environ["AMT"]
|
||||
hit=None
|
||||
for o in d.get("orders") or []:
|
||||
if o.get("amount")==want:
|
||||
hit=o; break
|
||||
if hit:
|
||||
print("ORDER", hit.get("order_id"), "amount", hit.get("amount"), "summary", hit.get("summary"))
|
||||
open("/tmp/oid.txt","w").write(hit.get("order_id") or "")
|
||||
else:
|
||||
print("NO_ORDER")
|
||||
open("/tmp/oid.txt","w").write("")
|
||||
PY' \
|
||||
'OID=$(tr -d "\n" </tmp/oid.txt 2>/dev/null || true)' \
|
||||
'if [ -n "$OID" ]; then
|
||||
curl -sk -H "$AUTH" "https://127.0.0.1:9010/instances/${INST}/private/orders/${OID}" -o /tmp/od.json
|
||||
python3 -c "import json;d=json.load(open(\"/tmp/od.json\"));print(\"DETAIL paid\",d.get(\"paid\"),\"status\",d.get(\"order_status\"),\"amount\",(d.get(\"contract_terms\")or{}).get(\"amount\"))"
|
||||
fi
|
||||
rm -f /tmp/ol.json /tmp/od.json /tmp/oid.txt' || true
|
||||
|
||||
status=unknown
|
||||
if grep -qE 'DETAIL paid True|DETAIL paid true' "$SCRATCH/koopa-ord$idx.out" 2>/dev/null; then
|
||||
status=paid
|
||||
elif grep -qiE 'insufficient balance' "$SCRATCH/pay-$idx-handle.out" 2>/dev/null; then
|
||||
status=insufficient
|
||||
elif grep -qiE 'error|fail|invalid|404|409|Unexpected HTTP' "$SCRATCH/pay-$idx-handle.out" 2>/dev/null; then
|
||||
status=error
|
||||
elif grep -qi 'paid' "$SCRATCH/pay-$idx-rud.out" 2>/dev/null; then
|
||||
status=maybe
|
||||
fi
|
||||
oid=$(awk '/^ORDER /{print $2; exit}' "$SCRATCH/koopa-ord$idx.out" 2>/dev/null || true)
|
||||
notes="load ${load_before}->${load_after}"
|
||||
echo "$idx,$AMT,$handle_s,$rud_s,$total_s,$status,$oid,$load_after,$notes" >>"$CSV"
|
||||
log "pay #$idx $AMT total=${total_s}s status=$status oid=$oid load=$load_after"
|
||||
wcli balance 2>&1 | tee "$SCRATCH/bal-after-$idx.out" || true
|
||||
done
|
||||
|
||||
sample_load final
|
||||
wcli balance 2>&1 | tee "$SCRATCH/balance-final.out" || true
|
||||
|
||||
python3 - "$CSV" "$SCRATCH" <<'PY' | tee "$SCRATCH/RESULTS.md"
|
||||
import csv, sys
|
||||
csv_path, scratch = sys.argv[1], sys.argv[2]
|
||||
rows = list(csv.DictReader(open(csv_path)))
|
||||
print("# Amount ladder payment benchmark")
|
||||
print()
|
||||
print(f"- Scratch: `{scratch}`")
|
||||
print(f"- Drive: Local-machine wallet-cli (external) · Measure: koopa podman (internal)")
|
||||
print(f"- Template: `goa-free` on `goa-demo-cp4zqk`")
|
||||
print(f"- URI: `taler://pay-template/…/instances/…/goa-free?amount=…` (no trailing slash, no summary)")
|
||||
print()
|
||||
print("| # | Amount | handle (s) | run-until-done (s) | **total (s)** | status | order | loadavg |")
|
||||
print("|--:|--------|----------:|-------------------:|--------------:|--------|-------|--------:|")
|
||||
for r in rows:
|
||||
print(f"| {r['idx']} | `{r['amount']}` | {r['handle_s']} | {r['rud_s']} | **{r['total_s']}** | {r['status']} | `{r.get('order_id','')}` | {r.get('loadavg','')} |")
|
||||
print()
|
||||
paid = [r for r in rows if r["status"] == "paid"]
|
||||
print(f"Paid **{len(paid)}/{len(rows)}**.")
|
||||
if paid:
|
||||
totals = [float(r["total_s"]) for r in paid if r["total_s"]]
|
||||
if totals:
|
||||
print(f"**Min** {min(totals):.3f}s · **Max** {max(totals):.3f}s · **Avg** {sum(totals)/len(totals):.3f}s")
|
||||
print()
|
||||
print("Inside samples: `koopa-load-*.out` in scratch.")
|
||||
PY
|
||||
|
||||
# durable copy of last RESULTS into benchmarks tree (no secrets)
|
||||
cp "$SCRATCH/RESULTS.md" "$BENCH_DIR/LAST_RESULTS.md"
|
||||
cp "$CSV" "$BENCH_DIR/LAST_payments.csv"
|
||||
log "DONE -> $SCRATCH/RESULTS.md (also benchmarks/amount-ladder/LAST_*)"
|
||||
cat "$SCRATCH/RESULTS.md"
|
||||
Loading…
Add table
Add a link
Reference in a new issue