rickub/ci-benchpublic Fork 0
4a60b11b698c40346344feead7fd7bc7a42195e6
Commits
Clone
git clone https://git.rickub.com/rickub/ci-bench.git
git clone ssh://git@rickub.com/rickub/ci-bench.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

ci-bench: cross-platform CI race scaffold (rickub CI vs GitHub Actions) 0baf736Unverified · on 4a60b11b698c40346344feead7fd7bc7a42195e6 · Olivier Girardot · yesterday
probe.sh · 132 lines · 4.6 KBBash Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env bash
# probe.sh — deterministic runner-capability probe. Every measurement degrades
# to a "null" value (still a recorded line) when a tool is missing; the job
# NEVER fails from the probe itself.
#
# Measurements:
#   probe-cpu       single-core shell-arithmetic loop throughput (kops/s over a
#                   fixed 1,000,000-iteration loop)
#   probe-write     sequential write throughput (dd 2 GiB to the job scratch
#                   dir, then removed)
#   probe-read      sequential read throughput of that same file
#   probe-fs-type   filesystem type of the scratch dir
#   probe-fs-free   free space of the scratch dir (MB)
#
# Usage: run from the repo root (the scripts/ dir next to workloads/):
#   bash workloads/probe/probe.sh

set -u

REPO_ROOT=$(cd "$(dirname "$0")/../.." && pwd)
# shellcheck disable=SC1091
. "$REPO_ROOT/scripts/emit_timing.sh"

# Scratch dir: the runner's temp when we have one, else mktemp -d.
PROBE_DIR=${RUNNER_TEMP:-${TMPDIR:-/tmp}}
mkdir -p "$PROBE_DIR" 2>/dev/null || PROBE_DIR=$(mktemp -d)
PROBE_BIN=$PROBE_DIR/probe.bin

now_s() { # fractional seconds, best available clock
    local t
    t=$(date -u +%s.%N 2>/dev/null || true)
    case $t in
        *N) t=$(python3 -c 'import time; print(f"{time.time():.6f}")' 2>/dev/null || echo '') ;;
    esac
    [ -n "$t" ] || t=$(date +%s).000
    printf '%s\n' "$t"
}

probe_cpu() {
    if ! command -v python3 >/dev/null 2>&1 && ! command -v bc >/dev/null 2>&1; then
        bench_metric probe-cpu null kops_per_s   # no fractional clock available
        return 0
    fi
    local iters=1000000 t0 t1 elapsed
    t0=$(now_s)
    local i=0
    while [ "$i" -lt "$iters" ]; do
        i=$((i + 1))
    done
    t1=$(now_s)
    if command -v python3 >/dev/null 2>&1; then
        elapsed=$(python3 -c "print(f'{$t1 - $t0:.6f}')")
    else
        elapsed=$(echo "$t1 - $t0" | bc -l)
    fi
    bench_metric probe-cpu "$(python3 -c "print(f'{$iters / $elapsed / 1000:.2f}')" 2>/dev/null \
        || echo "$iters $elapsed" | awk '{printf "%.2f", $1 / $2 / 1000}')" kops_per_s
}

# Parse the "bytes ... copied/transferred in N s" line dd writes to stderr.
# GNU: "X bytes (...) copied, 3.123 s, ...". BSD: "X bytes transferred in
# 3.123456 secs". Prints "BYTES SECONDS" on stdout, nothing when unmatched.
# ERE (-E) because BSD sed has no BRE alternation.
parse_dd() {
    sed -nE 's/^([0-9]+) bytes.*[ ,] ?([0-9.]+) s.*/\1 \2/p'
}

probe_write() {
    command -v dd >/dev/null 2>&1 || { bench_metric probe-write null MB_per_s; return 0; }
    local out
    out=$(dd if=/dev/zero of="$PROBE_BIN" bs=1M count=2048 2>&1) || true
    local parsed
    parsed=$(printf '%s\n' "$out" | parse_dd)
    if [ -z "$parsed" ]; then
        bench_metric probe-write null MB_per_s
        return 0
    fi
    set -- $parsed
    bench_metric probe-write "$(awk -v b="$1" -v s="$2" 'BEGIN { printf "%.1f", b / s / 1000000 }')" MB_per_s
}

probe_read() {
    if [ ! -f "$PROBE_BIN" ]; then
        bench_metric probe-read null MB_per_s   # write probe never produced it
        return 0
    fi
    command -v dd >/dev/null 2>&1 || { bench_metric probe-read null MB_per_s; return 0; }
    # Drop the page cache when we can (best effort, usually not permitted);
    # otherwise this measures warm cache — still comparable across platforms.
    sync 2>/dev/null || true
    local out
    out=$(dd if="$PROBE_BIN" of=/dev/null bs=1M 2>&1) || true
    local parsed
    parsed=$(printf '%s\n' "$out" | parse_dd)
    if [ -z "$parsed" ]; then
        bench_metric probe-read null MB_per_s
        return 0
    fi
    set -- $parsed
    bench_metric probe-read "$(awk -v b="$1" -v s="$2" 'BEGIN { printf "%.1f", b / s / 1000000 }')" MB_per_s
}

probe_fs() {
    # Filesystem type: GNU stat -f -c %T, BSD stat -f %T, else null.
    local fstype=null
    if stat -f -c %T "$PROBE_DIR" >/dev/null 2>&1; then
        fstype='"'$(stat -f -c %T "$PROBE_DIR" 2>/dev/null)'"'
    elif stat -f %T "$PROBE_DIR" >/dev/null 2>&1; then
        fstype='"'$(stat -f %T "$PROBE_DIR" 2>/dev/null | tr -d '"')'"'
    fi
    bench_metric probe-fs-type "$fstype" fstype

    # Free space in MB via df -k (POSIX), else null.
    if command -v df >/dev/null 2>&1; then
        local free_kb
        free_kb=$(df -Pk "$PROBE_DIR" 2>/dev/null | awk 'NR==2 {print $4}') || free_kb=''
        case $free_kb in
            ''|*[!0-9]*) bench_metric probe-fs-free null MB ;;
            *) bench_metric probe-fs-free "$((free_kb / 1024))" MB ;;
        esac
    else
        bench_metric probe-fs-free null MB
    fi
}

probe_cpu
probe_write
probe_read
rm -f "$PROBE_BIN" 2>/dev/null || true
probe_fs

exit 0