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
|