From e5a8f79fa9158a1c016ebf7563226a1b361cee61 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Mon, 26 Jan 2026 21:11:25 +0530 Subject: [PATCH 1/7] perf(geekbench): add reusable helpers for progress, parsing, and CSV outputs - Add POSIX-safe progress runner (fifo + heartbeat) without PIPESTATUS - Add summary/workload parsers and CSV init/append helpers - Add Geekbench bin resolver + unlock helper - Keep helpers self-contained for reuse by Geekbench runner Signed-off-by: Srikanth Muppandam --- Runner/utils/lib_performance.sh | 1193 +++++++++++++++++++++++++++++++ 1 file changed, 1193 insertions(+) diff --git a/Runner/utils/lib_performance.sh b/Runner/utils/lib_performance.sh index b4ba000f..def6997f 100755 --- a/Runner/utils/lib_performance.sh +++ b/Runner/utils/lib_performance.sh @@ -2755,3 +2755,1196 @@ perf_tiotest_gate_eval_line_safe() { echo "status=FAIL baseline=$base goal=$goal op=$op score_pct=$score key=${prefix}" return 1 } + +############################################################################### +# Geekbench / Performance reusable helpers for lib_performance.sh +############################################################################### +# ----------------------------------------------------------------------------- +# Small local-safe helpers (do not depend on other libs) +# ----------------------------------------------------------------------------- +perf_nowstamp_safe() { + if command -v nowstamp >/dev/null 2>&1; then + nowstamp + else + date "+%Y-%m-%d %H:%M:%S" 2>/dev/null || date + fi +} + +perf_is_number_safe() { + v=$1 + [ -n "$v" ] || return 1 + # Accept: 123 or 123.45 + case "$v" in + *[!0-9.]*|"."|*.*.*) return 1 ;; + esac + w=$v + if printf '%s' "$v" | grep -q '\.' 2>/dev/null; then + w=$(printf '%s' "$v" | tr -d '.') + fi + [ -n "$w" ] || return 1 + case "$w" in *[!0-9]*) return 1 ;; esac + return 0 +} + +perf_avg_file_safe() { + file=$1 + [ -f "$file" ] || return 0 + awk ' + $0 ~ /^[0-9]+(\.[0-9]+)?$/ { n++; s+=$0 } + END { if (n>0) printf "%.3f", s/n } + ' "$file" 2>/dev/null +} + +perf_csv_escape() { + # Escape for putting inside "...", double quotes + printf '%s' "$1" | sed 's/"/""/g' +} + +# POSIX-safe: preserve rc without PIPESTATUS (no tee pipeline). +# If perf_run_cmd_tee exists, use it (it should already be POSIX-safe in your tree). +perf_run_cmd_tee_safe() { + # perf_run_cmd_tee_safe LOGFILE -- cmd... + logfile=$1 + shift + if [ "${1:-}" = "--" ]; then + shift + fi + + : >"$logfile" 2>/dev/null || true + + if command -v perf_run_cmd_tee >/dev/null 2>&1; then + perf_run_cmd_tee "$logfile" "$@" + return $? + fi + + # Fallback: capture output to logfile, then print logfile to console. + if command -v stdbuf >/dev/null 2>&1; then + stdbuf -oL -eL "$@" >"$logfile" 2>&1 + rc=$? + else + "$@" >"$logfile" 2>&1 + rc=$? + fi + + cat "$logfile" 2>/dev/null || true + return "$rc" +} + +# ----------------------------------------------------------------------------- +# Basic file + log helper +# ----------------------------------------------------------------------------- + +# perf_write_and_log FILE MESSAGE... +# Append message to file and also log_info to console +perf_write_and_log() { + file=$1 + shift + msg=$* + [ -n "$file" ] || return 1 + printf "%s\n" "$msg" >>"$file" 2>/dev/null || true + if command -v log_info >/dev/null 2>&1; then + log_info "$msg" + else + printf "[INFO] %s\n" "$msg" + fi +} + +# ----------------------------------------------------------------------------- +# Live progress runner +# ----------------------------------------------------------------------------- + +# perf_run_cmd_with_progress OUTDIR RUN_LOG HEARTBEAT_SECS LABEL -- CMD... +# - Streams raw command output to console +# - Writes raw output to RUN_LOG +# - Emits log_info progress + heartbeat lines while running +# +# Requires: mkfifo, sleep, awk (stdbuf optional) +perf_run_cmd_with_progress() { + outdir=$1 + run_log=$2 + heartbeat_secs=$3 + label=$4 + shift 4 + + mkdir -p "${outdir:-.}" 2>/dev/null || true + : >"$run_log" 2>/dev/null || true + + case "${heartbeat_secs:-}" in + ""|*[!0-9]*) heartbeat_secs=15 ;; + esac + if [ "$heartbeat_secs" -lt 1 ] 2>/dev/null; then + heartbeat_secs=15 + fi + + if [ "${1:-}" != "--" ]; then + log_warn "perf_run_cmd_with_progress: missing -- separator, falling back to tee" + perf_run_cmd_tee_safe "$run_log" -- "$@" + return $? + fi + shift + + tmpdir=$(mktemp -d "$outdir/.perftmp.XXXXXX" 2>/dev/null) + if [ -z "${tmpdir:-}" ] || [ ! -d "$tmpdir" ]; then + tmpdir=$(mktemp -d 2>/dev/null) + fi + if [ -z "${tmpdir:-}" ] || [ ! -d "$tmpdir" ]; then + log_warn "perf_run_cmd_with_progress: mktemp failed, falling back to tee" + perf_run_cmd_tee_safe "$run_log" -- "$@" + return $? + fi + + fifo="$tmpdir/fifo" + status_file="$tmpdir/status" + : >"$status_file" 2>/dev/null || true + + if ! mkfifo "$fifo" 2>/dev/null; then + rm -rf "$tmpdir" 2>/dev/null || true + log_warn "perf_run_cmd_with_progress: mkfifo failed, falling back to tee" + perf_run_cmd_tee_safe "$run_log" -- "$@" + return $? + fi + + log_info "Progress, $label, started" + log_info "Progress, command, $*" + printf "%s\n" "$label, invoked, waiting for output" >"$status_file" 2>/dev/null || true + + if command -v stdbuf >/dev/null 2>&1; then + (stdbuf -oL -eL "$@" >"$fifo" 2>&1) & + else + ("$@" >"$fifo" 2>&1) & + fi + pid=$! + + ( + while kill -0 "$pid" 2>/dev/null; do + sleep "$heartbeat_secs" 2>/dev/null || break + if kill -0 "$pid" 2>/dev/null; then + s=$(cat "$status_file" 2>/dev/null) + if [ -n "${s:-}" ]; then + log_info "Progress, $s, still running" + fi + fi + done + ) & + hbpid=$! + + mode="" + sc=0 + mc=0 + + while IFS= read -r line; do + printf "%s\n" "$line" + printf "%s\n" "$line" >>"$run_log" 2>/dev/null || true + + case "$line" in + "Single-Core") + mode="Single-Core" + sc=0 + printf "%s\n" "$label, entered Single-Core" >"$status_file" 2>/dev/null || true + log_info "Progress, $label, entered Single-Core" + continue + ;; + "Multi-Core") + mode="Multi-Core" + mc=0 + printf "%s\n" "$label, entered Multi-Core" >"$status_file" 2>/dev/null || true + log_info "Progress, $label, entered Multi-Core" + continue + ;; + "Benchmark Summary") + # Fix-1: stop workload tracking at summary to avoid + # "Single-Core Score / Integer Score / Floating Point Score" being seen as workloads. + mode="" + printf "%s\n" "$label, entered Benchmark Summary" >"$status_file" 2>/dev/null || true + log_info "Progress, $label, entered Benchmark Summary" + continue + ;; + "System Information"|"CPU Information"|"Memory Information") + # Defensive: these are not workloads; stop tracking. + mode="" + printf "%s\n" "$label, entered $line" >"$status_file" 2>/dev/null || true + log_info "Progress, $label, entered $line" + continue + ;; + esac + + if [ -n "$mode" ]; then + name=$( + printf "%s\n" "$line" | + awk ' + function trim(s){ sub(/^[ \t]+/,"",s); sub(/[ \t]+$/,"",s); return s } + { + first=0 + for(i=1;i<=NF;i++){ + if($i ~ /^[0-9]+$/){ first=i; break } + } + if(first<=1) exit 1 + out="" + for(i=1;i/dev/null + ) + + if [ -n "${name:-}" ]; then + if [ "$mode" = "Single-Core" ]; then + sc=$((sc + 1)) + printf "%s\n" "$label, Single-Core, $sc, $name" >"$status_file" 2>/dev/null || true + log_info "Progress, $label, Single-Core, $sc, $name" + else + mc=$((mc + 1)) + printf "%s\n" "$label, Multi-Core, $mc, $name" >"$status_file" 2>/dev/null || true + log_info "Progress, $label, Multi-Core, $mc, $name" + fi + fi + fi + done <"$fifo" + + wait "$pid" + rc=$? + + kill "$hbpid" 2>/dev/null || true + wait "$hbpid" 2>/dev/null || true + + rm -rf "$tmpdir" 2>/dev/null || true + + if [ "$rc" -eq 0 ]; then + log_info "Progress, $label, completed, rc, 0" + else + log_warn "Progress, $label, completed, rc, $rc" + fi + + return "$rc" +} + +# ----------------------------------------------------------------------------- +# Parsers, summary + workloads +# ----------------------------------------------------------------------------- +# perf_parse_geekbench_summary_scores LOGFILE +# Prints: single_total single_int single_fp multi_total multi_int multi_fp +# Prints: st|si|sf|mt|mi|mf +perf_parse_geekbench_summary_scores() { + logfile=$1 + [ -n "$logfile" ] || return 1 + [ -f "$logfile" ] || return 1 + + awk ' + function clean(line) { + gsub(/\r/, "", line) + # strip common ANSI CSI sequences (best effort) + gsub(/\033\[[0-9;]*[A-Za-z]/, "", line) + return line + } + function last_int(line, n,a,i,t) { + n=split(line, a, /[[:space:]]+/) + for (i=n; i>=1; i--) { + t=a[i] + gsub(/\033\[[0-9;]*[A-Za-z]/, "", t) + if (t ~ /^[0-9]+$/) return t + } + return "" + } + + BEGIN{ + in_summary=0 + cur="" + st=""; si=""; sf="" + mt=""; mi=""; mf="" + } + + { $0 = clean($0) } + + # Start summary (allow indentation) + /^[[:space:]]*Benchmark Summary[[:space:]]*$/ { in_summary=1; cur=""; next } + + in_summary==1 { + # If a new big header begins, stop + if ($0 ~ /^[[:space:]]*System Information[[:space:]]*$/) { in_summary=0; next } + if ($0 ~ /^[[:space:]]*CPU Information[[:space:]]*$/) { in_summary=0; next } + if ($0 ~ /^[[:space:]]*Memory Information[[:space:]]*$/) { in_summary=0; next } + + if (index($0, "Single-Core Score") > 0) { + v = last_int($0) + if (v != "") { st=v; cur="single" } + next + } + if (index($0, "Multi-Core Score") > 0) { + v = last_int($0) + if (v != "") { mt=v; cur="multi" } + next + } + + if (index($0, "Integer Score") > 0) { + v = last_int($0) + if (v != "") { + if (cur=="single" && si=="") si=v + else if (cur=="multi" && mi=="") mi=v + } + next + } + if (index($0, "Floating Point Score") > 0) { + v = last_int($0) + if (v != "") { + if (cur=="single" && sf=="") sf=v + else if (cur=="multi" && mf=="") mf=v + } + next + } + next + } + + END{ + if (st!="" || mt!="") { + printf "%s|%s|%s|%s|%s|%s\n", st, si, sf, mt, mi, mf + } + } + ' "$logfile" 2>/dev/null +} + +# perf_append_geekbench_workloads_csv LOGFILE TIMESTAMP TESTNAME ITER CSVFILE +# Appends rows: +# timestamp,test,iter,core_mode,workload,score,throughput +perf_append_geekbench_workloads_csv() { + logfile=$1 + ts=$2 + testname=$3 + iter=$4 + csvfile=$5 + + [ -n "$logfile" ] || return 1 + [ -n "$ts" ] || return 1 + [ -n "$testname" ] || return 1 + [ -n "$iter" ] || return 1 + [ -n "$csvfile" ] || return 1 + + awk -v ts="$ts" -v test="$testname" -v iter="$iter" ' + function trim(s){ sub(/^[ \t]+/,"",s); sub(/[ \t]+$/,"",s); return s } + BEGIN{ mode=""; } + + /^[[:space:]]*Benchmark Summary/ { exit } + + /^[[:space:]]*Single-Core[[:space:]]*$/ { mode="Single-Core"; next } + /^[[:space:]]*Multi-Core[[:space:]]*$/ { mode="Multi-Core"; next } + + mode!="" { + score=""; name=""; thr=""; first=0 + + for (i=1;i<=NF;i++){ + if ($i ~ /^[0-9]+$/) { first=i; score=$i; break } + } + if (first==0) next + + for (i=1;i>"$csvfile" 2>/dev/null || true +} + + +# ----------------------------------------------------------------------------- +# Geekbench “readable” CSV init helpers (2 files) +# ----------------------------------------------------------------------------- +perf_geekbench_summary_csv_init() { + csvfile=$1 + [ -n "$csvfile" ] || return 0 + if [ ! -f "$csvfile" ] || [ ! -s "$csvfile" ]; then + printf '%s\n' "timestamp,test,iteration,single_total,single_integer,single_float,multi_total,multi_integer,multi_float" >"$csvfile" 2>/dev/null || true + fi + return 0 +} + +# perf_geekbench_workloads_csv_init FILE +perf_geekbench_workloads_csv_init() { + csvfile=$1 + [ -n "$csvfile" ] || return 0 + if [ ! -f "$csvfile" ] || [ ! -s "$csvfile" ]; then + printf '%s\n' "timestamp,test,iteration,core_mode,workload,score,throughput" >"$csvfile" 2>/dev/null || true + fi + return 0 +} + + +perf_geekbench_write_iter_summary_txt() { + st=$1; si=$2; sf=$3 + mt=$4; mi=$5; mf=$6 + outfile=$7 + + [ -n "$outfile" ] || return 1 + + : >"$outfile" 2>/dev/null || true + + if [ -n "${st:-}" ]; then + echo "Benchmark Summary" >>"$outfile" + echo " Single-Core Score: ${st}" >>"$outfile" + [ -n "${si:-}" ] && echo " Integer Score: ${si}" >>"$outfile" + [ -n "${sf:-}" ] && echo " Floating Point Score: ${sf}" >>"$outfile" + echo "" >>"$outfile" + fi + + if [ -n "${mt:-}" ]; then + echo "Benchmark Summary" >>"$outfile" + echo " Multi-Core Score: ${mt}" >>"$outfile" + [ -n "${mi:-}" ] && echo " Integer Score: ${mi}" >>"$outfile" + [ -n "${mf:-}" ] && echo " Floating Point Score: ${mf}" >>"$outfile" + echo "" >>"$outfile" + fi + + if [ -z "${st:-}" ] && [ -z "${mt:-}" ]; then + echo "Benchmark Summary present but totals could not be parsed." >>"$outfile" + fi + + return 0 +} + +# perf_geekbench_write_iter_subscores_txt LOGFILE OUTFILE +# Writes a readable list: +# Single-Core workloads: +# - Foo: 123 +# Multi-Core workloads: +# - Bar: 456 +perf_geekbench_write_iter_subscores_txt() { + logfile=$1 + outfile=$2 + + [ -n "$logfile" ] || return 1 + [ -n "$outfile" ] || return 1 + [ -f "$logfile" ] || return 1 + + awk ' + function trim(s){ sub(/^[ \t]+/,"",s); sub(/[ \t]+$/,"",s); return s } + BEGIN{ mode=""; printed_sc=0; printed_mc=0 } + + /^[[:space:]]*Benchmark Summary/ { exit } + + /^[[:space:]]*Single-Core[[:space:]]*$/ { + mode="Single-Core" + if (!printed_sc) { print "Single-Core workloads:"; printed_sc=1 } + next + } + /^[[:space:]]*Multi-Core[[:space:]]*$/ { + mode="Multi-Core" + if (!printed_mc) { print ""; print "Multi-Core workloads:"; printed_mc=1 } + next + } + + mode!="" { + score=""; name=""; first=0 + + for (i=1;i<=NF;i++){ + if ($i ~ /^[0-9]+$/) { first=i; score=$i; break } + } + if (first==0) next + + for (i=1;i"$outfile" 2>/dev/null || true +} + +# perf_geekbench_scores_to_vars SCORELINE +# Input: "st|si|sf|mt|mi|mf" +# Output: prints 6 lines "st=..", etc (for eval) +perf_geekbench_scores_to_vars() { + s=$1 + [ -n "$s" ] || return 1 + + # Split without relying on bash arrays + st=$(printf '%s' "$s" | awk -F'|' '{print $1}') + si=$(printf '%s' "$s" | awk -F'|' '{print $2}') + sf=$(printf '%s' "$s" | awk -F'|' '{print $3}') + mt=$(printf '%s' "$s" | awk -F'|' '{print $4}') + mi=$(printf '%s' "$s" | awk -F'|' '{print $5}') + mf=$(printf '%s' "$s" | awk -F'|' '{print $6}') + + # Quote values safely for eval. Values are numeric/empty, but keep it robust. + printf "st='%s'\n" "$(printf '%s' "$st" | sed "s/'/'\\\\''/g")" + printf "si='%s'\n" "$(printf '%s' "$si" | sed "s/'/'\\\\''/g")" + printf "sf='%s'\n" "$(printf '%s' "$sf" | sed "s/'/'\\\\''/g")" + printf "mt='%s'\n" "$(printf '%s' "$mt" | sed "s/'/'\\\\''/g")" + printf "mi='%s'\n" "$(printf '%s' "$mi" | sed "s/'/'\\\\''/g")" + printf "mf='%s'\n" "$(printf '%s' "$mf" | sed "s/'/'\\\\''/g")" +} + +# perf_geekbench_has_benchmark_summary LOGFILE +# Returns 0 if "Benchmark Summary" header appears (allow indentation) +perf_geekbench_has_benchmark_summary() { + f=$1 + [ -n "$f" ] || return 1 + [ -f "$f" ] || return 1 + grep -q '[[:space:]]*Benchmark Summary[[:space:]]*$' "$f" 2>/dev/null +} + +# perf_geekbench_log_subscores_file FILE +# Prints file lines using log_info (if available), otherwise echo. +perf_geekbench_log_subscores_file() { + f=$1 + [ -n "$f" ] || return 1 + [ -s "$f" ] || return 1 + + if command -v log_info >/dev/null 2>&1; then + while IFS= read -r line; do + [ -n "$line" ] || continue + log_info "$line" + done <"$f" + else + cat "$f" + fi + return 0 +} + +# perf_geekbench_log_summary_scores ST SI SF MT MI MF +# Logs a "Benchmark Summary (this run)" block (single-only or multi-only) +perf_geekbench_log_summary_scores() { + st=$1; si=$2; sf=$3 + mt=$4; mi=$5; mf=$6 + + if command -v log_info >/dev/null 2>&1; then + log_info "Geekbench summary (this run):" + if [ -n "${st:-}" ] && perf_is_number_safe "$st"; then + log_info " Single-Core Score : $st" + if [ -n "${si:-}" ] && perf_is_number_safe "$si"; then log_info " Integer Score : $si"; fi + if [ -n "${sf:-}" ] && perf_is_number_safe "$sf"; then log_info " FP Score : $sf"; fi + fi + if [ -n "${mt:-}" ] && perf_is_number_safe "$mt"; then + log_info " Multi-Core Score : $mt" + if [ -n "${mi:-}" ] && perf_is_number_safe "$mi"; then log_info " Integer Score : $mi"; fi + if [ -n "${mf:-}" ] && perf_is_number_safe "$mf"; then log_info " FP Score : $mf"; fi + fi + else + echo "Geekbench summary (this run):" + [ -n "${st:-}" ] && echo " Single-Core Score : $st" + [ -n "${si:-}" ] && echo " Integer Score : $si" + [ -n "${sf:-}" ] && echo " FP Score : $sf" + [ -n "${mt:-}" ] && echo " Multi-Core Score : $mt" + [ -n "${mi:-}" ] && echo " Integer Score : $mi" + [ -n "${mf:-}" ] && echo " FP Score : $mf" + fi + return 0 +} +# ----------------------------------------------------------------------------- +# Geekbench bin + unlock helpers +# ----------------------------------------------------------------------------- +perf_geekbench_pick_bin() { + # Optional override: can be a directory or a file or a command name + # Backward compatible: if not given, uses $GEEKBENCH_BIN then PATH. + spec=$1 + + if [ -z "${spec:-}" ]; then + spec=${GEEKBENCH_BIN:-} + fi + + # If user provided a directory, pick executable inside it and fix +x + if [ -n "${spec:-}" ] && [ -d "$spec" ]; then + # try common names inside bundle + for cand in "$spec/geekbench_aarch64" "$spec/geekbench" "$spec/geekbench6_aarch64" "$spec/geekbench6"; do + if [ -f "$cand" ]; then + if [ ! -x "$cand" ]; then + chmod +x "$cand" 2>/dev/null || true + fi + # Also fix common wrapper scripts if present (best effort) + for w in "$spec/run.sh" "$spec/Geekbench" "$spec/geekbench.sh"; do + if [ -f "$w" ] && [ ! -x "$w" ]; then + chmod +x "$w" 2>/dev/null || true + fi + done + if [ -x "$cand" ]; then + echo "$cand" + return 0 + fi + fi + done + echo "" + return 1 + fi + + # If user provided a file path, chmod +x if needed + if [ -n "${spec:-}" ] && [ -f "$spec" ]; then + if [ ! -x "$spec" ]; then + chmod +x "$spec" 2>/dev/null || true + fi + if [ -x "$spec" ]; then + echo "$spec" + return 0 + fi + echo "" + return 1 + fi + + # If user provided a command name present in PATH + if [ -n "${spec:-}" ] && command -v "$spec" >/dev/null 2>&1; then + p=$(command -v "$spec" 2>/dev/null) + # best effort chmod if it is a file and not exec (rare) + if [ -n "${p:-}" ] && [ -f "$p" ] && [ ! -x "$p" ]; then + chmod +x "$p" 2>/dev/null || true + fi + if [ -n "${p:-}" ] && [ -x "$p" ]; then + echo "$p" + return 0 + fi + fi + + # Default PATH lookup + if command -v geekbench_aarch64 >/dev/null 2>&1; then + p=$(command -v geekbench_aarch64 2>/dev/null) + if [ -n "${p:-}" ] && [ -f "$p" ] && [ ! -x "$p" ]; then + chmod +x "$p" 2>/dev/null || true + fi + if [ -n "${p:-}" ] && [ -x "$p" ]; then + echo "$p" + return 0 + fi + fi + + if command -v geekbench >/dev/null 2>&1; then + p=$(command -v geekbench 2>/dev/null) + if [ -n "${p:-}" ] && [ -f "$p" ] && [ ! -x "$p" ]; then + chmod +x "$p" 2>/dev/null || true + fi + if [ -n "${p:-}" ] && [ -x "$p" ]; then + echo "$p" + return 0 + fi + fi + + echo "" + return 1 +} + +# ----------------------------------------------------------------------------- +# Geekbench bin resolver + chmod fix (reusable) +# ----------------------------------------------------------------------------- +perf_geekbench_fix_exec_perms_dir() { + d=$1 + [ -n "$d" ] || return 1 + [ -d "$d" ] || return 1 + + # Best effort: known names in Geekbench bundles + for f in \ + "$d/geekbench_aarch64" \ + "$d/geekbench" \ + "$d/Geekbench"* \ + "$d/geekbench"*; do + [ -f "$f" ] || continue + if [ ! -x "$f" ]; then + chmod +x "$f" 2>/dev/null || true + fi + done + return 0 +} + +# perf_geekbench_resolve_bin_and_fix_perms REQUESTED +# - REQUESTED can be: empty, command, file path, or directory path +# - Prints resolved executable path to stdout +perf_geekbench_resolve_bin_and_fix_perms() { + req=$1 + + # empty -> try PATH candidates + if [ -z "${req:-}" ]; then + if command -v geekbench_aarch64 >/dev/null 2>&1; then + command -v geekbench_aarch64 2>/dev/null + return 0 + fi + if command -v geekbench >/dev/null 2>&1; then + command -v geekbench 2>/dev/null + return 0 + fi + return 1 + fi + + # directory provided + if [ -d "$req" ]; then + perf_geekbench_fix_exec_perms_dir "$req" 2>/dev/null || true + + if [ -f "$req/geekbench_aarch64" ]; then + [ -x "$req/geekbench_aarch64" ] || chmod +x "$req/geekbench_aarch64" 2>/dev/null || true + echo "$req/geekbench_aarch64" + return 0 + fi + if [ -f "$req/geekbench" ]; then + [ -x "$req/geekbench" ] || chmod +x "$req/geekbench" 2>/dev/null || true + echo "$req/geekbench" + return 0 + fi + + # last resort: pick first file matching geekbench* + for f in "$req"/geekbench* "$req"/Geekbench*; do + [ -f "$f" ] || continue + [ -x "$f" ] || chmod +x "$f" 2>/dev/null || true + echo "$f" + return 0 + done + return 1 + fi + + # file provided + if [ -f "$req" ]; then + [ -x "$req" ] || chmod +x "$req" 2>/dev/null || true + echo "$req" + return 0 + fi + + # command provided + if command -v "$req" >/dev/null 2>&1; then + p=$(command -v "$req" 2>/dev/null) + [ -n "$p" ] || return 1 + echo "$p" + return 0 + fi + + return 1 +} + +perf_geekbench_unlock_if_requested() { + bin=$1 + email=$2 + key=$3 + logf=$4 + + [ -n "$bin" ] || return 1 + [ -n "$email" ] || return 0 + [ -n "$key" ] || return 0 + [ -n "$logf" ] || logf="./geekbench_unlock.log" + + : >"$logf" 2>/dev/null || true + if command -v log_info >/dev/null 2>&1; then + log_info "Geekbench, unlock requested, log, $logf" + fi + + perf_run_cmd_tee_safe "$logf" -- "$bin" --unlock "$email" "$key" + rc=$? + + if [ "$rc" -eq 0 ]; then + if command -v log_info >/dev/null 2>&1; then + log_info "Geekbench, unlock done, rc, 0" + fi + return 0 + fi + + if grep -qi "already" "$logf" 2>/dev/null; then + if command -v log_info >/dev/null 2>&1; then + log_info "Geekbench, already unlocked, continuing" + fi + return 0 + fi + + if command -v log_warn >/dev/null 2>&1; then + log_warn "Geekbench, unlock failed, rc, $rc, continuing" + fi + return 1 +} + +# ----------------------------------------------------------------------------- +# Runner: run Geekbench N times and dump 2 readable CSVs (summary + workloads) +# Uses live progress streaming via perf_run_cmd_with_progress +# ----------------------------------------------------------------------------- + +# perf_geekbench_run_and_dump_csv BIN OUTDIR TESTNAME ITERS SUMMARY_CSV WORKLOADS_CSV HEARTBEAT_SECS -- GEEKBENCH_ARGS... +perf_geekbench_run_and_dump_csv() { + bin=$1 + outdir=$2 + testname=$3 + iters=$4 + summary_csv=$5 + workloads_csv=$6 + heartbeat_secs=$7 + shift 7 + + if [ "${1:-}" = "--" ]; then + shift + fi + + [ -n "$bin" ] || return 1 + [ -n "$outdir" ] || outdir="." + [ -n "$testname" ] || testname="geekbench" + case "${iters:-}" in ""|*[!0-9]*) iters=1 ;; esac + [ "$iters" -lt 1 ] && iters=1 + + mkdir -p "$outdir" 2>/dev/null || true + perf_geekbench_summary_csv_init "$summary_csv" + perf_geekbench_workloads_csv_init "$workloads_csv" + + vst="$outdir/${testname}_sum_single_total.values" + vsi="$outdir/${testname}_sum_single_integer.values" + vsf="$outdir/${testname}_sum_single_fp.values" + vmt="$outdir/${testname}_sum_multi_total.values" + vmi="$outdir/${testname}_sum_multi_integer.values" + vmf="$outdir/${testname}_sum_multi_fp.values" + : >"$vst" 2>/dev/null || true + : >"$vsi" 2>/dev/null || true + : >"$vsf" 2>/dev/null || true + : >"$vmt" 2>/dev/null || true + : >"$vmi" 2>/dev/null || true + : >"$vmf" 2>/dev/null || true + + i=1 + while [ "$i" -le "$iters" ]; do + ts=$(perf_nowstamp_safe) + run_log="$outdir/${testname}_iter${i}.log" + label="$testname, iter, $i, of, $iters" + + if command -v log_info >/dev/null 2>&1; then + log_info "Geekbench, iteration, $i, of, $iters" + fi + + perf_run_cmd_with_progress "$outdir" "$run_log" "$heartbeat_secs" "$label" -- "$bin" "$@" + rc=$? + + if [ "$rc" -ne 0 ] && command -v log_warn >/dev/null 2>&1; then + log_warn "Geekbench, iteration, $i, rc, $rc, continuing, parse" + fi + + if grep -q '^Benchmark Summary' "$run_log" 2>/dev/null; then + scores=$(perf_parse_geekbench_summary_scores "$run_log") + st=$(printf '%s\n' "$scores" | awk '{print $1}') + si=$(printf '%s\n' "$scores" | awk '{print $2}') + sf=$(printf '%s\n' "$scores" | awk '{print $3}') + mt=$(printf '%s\n' "$scores" | awk '{print $4}') + mi=$(printf '%s\n' "$scores" | awk '{print $5}') + mf=$(printf '%s\n' "$scores" | awk '{print $6}') + + echo "$ts,$testname,$i,$st,$si,$sf,$mt,$mi,$mf" >>"$summary_csv" 2>/dev/null || true + perf_append_geekbench_workloads_csv "$run_log" "$ts" "$testname" "$i" "$workloads_csv" + + # POSIX-safe, ShellCheck-safe (no A&&B||true) + if perf_is_number_safe "$st"; then + printf '%s\n' "$st" >>"$vst" 2>/dev/null || true + fi + if perf_is_number_safe "$si"; then + printf '%s\n' "$si" >>"$vsi" 2>/dev/null || true + fi + if perf_is_number_safe "$sf"; then + printf '%s\n' "$sf" >>"$vsf" 2>/dev/null || true + fi + if perf_is_number_safe "$mt"; then + printf '%s\n' "$mt" >>"$vmt" 2>/dev/null || true + fi + if perf_is_number_safe "$mi"; then + printf '%s\n' "$mi" >>"$vmi" 2>/dev/null || true + fi + if perf_is_number_safe "$mf"; then + printf '%s\n' "$mf" >>"$vmf" 2>/dev/null || true + fi + else + if command -v log_info >/dev/null 2>&1; then + log_info "Geekbench, no benchmark summary for iter, $i, mode like sysinfo or list is ok" + fi + fi + + i=$((i + 1)) + done + + ast=$(perf_avg_file_safe "$vst") + asi=$(perf_avg_file_safe "$vsi") + asf=$(perf_avg_file_safe "$vsf") + amt=$(perf_avg_file_safe "$vmt") + ami=$(perf_avg_file_safe "$vmi") + amf=$(perf_avg_file_safe "$vmf") + + if [ -n "$ast" ] || [ -n "$amt" ]; then + ts=$(perf_nowstamp_safe) + echo "$ts,$testname,avg,$ast,$asi,$asf,$amt,$ami,$amf" >>"$summary_csv" 2>/dev/null || true + fi + + if command -v log_info >/dev/null 2>&1; then + log_info "Geekbench, csv, summary, $summary_csv" + log_info "Geekbench, csv, workloads, $workloads_csv" + fi + return 0 +} + +# ----------------------------------------------------------------------------- +# ALL-metrics extraction (long-format CSV) +# ----------------------------------------------------------------------------- + +perf_geekbench_sanitize_key() { + printf '%s' "$1" | tr ' ' '_' | tr -cd 'A-Za-z0-9._-' +} + +# perf_geekbench_extract_metrics_from_text FILE +# Emits TSV: metricvalueunitkind +perf_geekbench_extract_metrics_from_text() { + file=$1 + [ -f "$file" ] || return 1 + + awk ' + function trim(s) { sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s); return s } + function join_name(a, start, end, s,i) { + s="" + for (i=start; i<=end; i++) { + if (s=="") s=a[i]; else s=s" "a[i] + } + return s + } + function emit(metric, value, unit, kind) { + if (unit=="") unit="NA" + if (kind=="") kind="NA" + printf "%s\t%s\t%s\t%s\n", metric, value, unit, kind + } + + BEGIN { section=""; sum_mode="" } + + /^Single-Core[[:space:]]*$/ { section="single"; next } + /^Multi-Core[[:space:]]*$/ { section="multi"; next } + /^Benchmark Summary[[:space:]]*$/ { section="summary"; sum_mode=""; next } + + section=="summary" { + line=$0 + if (match(line, /Single-Core Score[[:space:]]+[0-9]+/)) { + sum_mode="single" + v=line; sub(/.*Single-Core Score[[:space:]]+/, "", v); v=trim(v) + emit("geekbench.summary.single.total_score", v, "score", "summary") + next + } + if (match(line, /Multi-Core Score[[:space:]]+[0-9]+/)) { + sum_mode="multi" + v=line; sub(/.*Multi-Core Score[[:space:]]+/, "", v); v=trim(v) + emit("geekbench.summary.multi.total_score", v, "score", "summary") + next + } + if (sum_mode!="") { + if (match(line, /Integer Score[[:space:]]+[0-9]+/)) { + v=line; sub(/.*Integer Score[[:space:]]+/, "", v); v=trim(v) + emit("geekbench.summary."sum_mode".integer_score", v, "score", "summary") + next + } + if (match(line, /Floating Point Score[[:space:]]+[0-9]+/)) { + v=line; sub(/.*Floating Point Score[[:space:]]+/, "", v); v=trim(v) + emit("geekbench.summary."sum_mode".floating_point_score", v, "score", "summary") + next + } + } + next + } + + (section=="single" || section=="multi") { + line=trim($0) + if (line=="") next + if (line ~ /^Geekbench /) next + if (line ~ /^System Information/ || line ~ /^CPU Information/ || line ~ /^Memory Information/) next + if (line ~ /^Operating System/ || line ~ /^Kernel/ || line ~ /^Model/ || line ~ /^Motherboard/) next + if (line ~ /^Name/ || line ~ /^Topology/ || line ~ /^Identifier/ || line ~ /^Base Frequency/) next + if (line ~ /^Size/) next + if (line ~ /^Benchmark Summary/) next + + n=split(line, a, /[[:space:]]+/) + if (n < 4) next + + unit=a[n] + thr=a[n-1] + score="" + score_i=0 + + for (i=n-2; i>=1; i--) { + if (a[i] ~ /^[0-9]+$/) { score=a[i]; score_i=i; break } + } + if (score=="") next + + name=join_name(a, 1, score_i-1) + name=trim(name) + if (name=="") next + + emit("geekbench."section".workload."name".score", score, "score", "workload") + + if (thr ~ /^[0-9]+(\.[0-9]+)?$/) { + emit("geekbench."section".workload."name".throughput", thr, unit, "throughput") + } else { + emit("geekbench."section".workload."name".throughput", "", unit, "throughput") + } + next + } + ' "$file" +} + +# Long CSV append: timestamp,test,metric,iteration,value,extra +perf_geekbench_csv_append() { + csv=$1 + test=$2 + metric=$3 + iter=$4 + value=$5 + extra=$6 + + [ -n "$csv" ] || return 0 + + dir=$(dirname "$csv") + mkdir -p "$dir" 2>/dev/null || true + + if [ ! -f "$csv" ] || [ ! -s "$csv" ]; then + echo "timestamp,test,metric,iteration,value,extra" >"$csv" + fi + + ts=$(perf_nowstamp_safe) + + mq=$(perf_csv_escape "$metric") + eq=$(perf_csv_escape "${extra:-}") + + echo "$ts,$test,\"$mq\",$iter,$value,\"$eq\"" >>"$csv" 2>/dev/null || true +} + +perf_geekbench_metric_seen_add() { + listf=$1 + metric=$2 + [ -n "$listf" ] || return 0 + [ -n "$metric" ] || return 0 + if [ ! -f "$listf" ] || ! grep -qxF "$metric" "$listf" 2>/dev/null; then + echo "$metric" >>"$listf" 2>/dev/null || true + fi +} + +perf_geekbench_values_file_for_metric() { + outdir=$1 + metric=$2 + safe=$(perf_geekbench_sanitize_key "$metric") + printf '%s/%s.values' "$outdir" "$safe" +} + +perf_geekbench_append_if_number() { + file=$1 + value=$2 + [ -n "$file" ] || return 0 + [ -n "$value" ] || return 0 + if perf_is_number_safe "$value"; then + printf '%s\n' "$value" >>"$file" 2>/dev/null || true + fi +} + +# perf_geekbench_run_n_dump_all_metrics BIN OUTDIR TESTNAME ITERS LONGCSV EXTRA HEARTBEAT_SECS -- GEEKBENCH_ARGS... +# Prints: single_total_avg=... multi_total_avg=... +perf_geekbench_run_n_dump_all_metrics() { + bin=$1 + outdir=$2 + testname=$3 + iters=$4 + csv=$5 + extra=$6 + heartbeat_secs=$7 + shift 7 + + if [ "${1:-}" = "--" ]; then + shift + fi + + [ -n "$bin" ] || return 1 + [ -n "$outdir" ] || outdir="." + [ -n "$testname" ] || testname="geekbench" + case "${iters:-}" in ""|*[!0-9]*) iters=1 ;; esac + [ "$iters" -lt 1 ] && iters=1 + + mkdir -p "$outdir" 2>/dev/null || true + + metrics_list="$outdir/${testname}_metrics.list" + : >"$metrics_list" 2>/dev/null || true + + single_vals="$outdir/${testname}_single_total.values" + multi_vals="$outdir/${testname}_multi_total.values" + : >"$single_vals" 2>/dev/null || true + : >"$multi_vals" 2>/dev/null || true + + i=1 + while [ "$i" -le "$iters" ]; do + run_log="$outdir/${testname}_iter${i}.log" + txt_out="$outdir/${testname}_iter${i}.txt" + met_out="$outdir/${testname}_iter${i}.metrics.tsv" + label="$testname, metrics, iter, $i, of, $iters" + + if command -v log_info >/dev/null 2>&1; then + log_info "Geekbench, iteration, $i, of, $iters, export-text, $txt_out" + fi + + perf_run_cmd_with_progress "$outdir" "$run_log" "$heartbeat_secs" "$label" -- \ + "$bin" "$@" --export-text "$txt_out" + rc=$? + + if [ "$rc" -ne 0 ] && command -v log_warn >/dev/null 2>&1; then + log_warn "Geekbench, iter, $i, rc, $rc, continuing" + fi + + src="$txt_out" + if [ ! -f "$src" ]; then + src="$run_log" + fi + + : >"$met_out" 2>/dev/null || true + perf_geekbench_extract_metrics_from_text "$src" >"$met_out" 2>/dev/null || true + + if [ ! -s "$met_out" ]; then + if command -v log_warn >/dev/null 2>&1; then + log_warn "Geekbench, iter, $i, no metrics extracted" + fi + i=$((i + 1)) + continue + fi + + while IFS="$(printf '\t')" read -r metric value unit kind; do + [ -n "$metric" ] || continue + + perf_geekbench_metric_seen_add "$metrics_list" "$metric" + ex="$extra unit=${unit:-NA} kind=${kind:-NA}" + perf_geekbench_csv_append "$csv" "$testname" "$metric" "$i" "${value:-}" "$ex" + + vf=$(perf_geekbench_values_file_for_metric "$outdir" "$metric") + perf_geekbench_append_if_number "$vf" "$value" + + if [ "$metric" = "geekbench.summary.single.total_score" ]; then + perf_geekbench_append_if_number "$single_vals" "$value" + fi + if [ "$metric" = "geekbench.summary.multi.total_score" ]; then + perf_geekbench_append_if_number "$multi_vals" "$value" + fi + done <"$met_out" + + i=$((i + 1)) + done + + if [ -s "$metrics_list" ]; then + while IFS= read -r metric; do + [ -n "$metric" ] || continue + vf=$(perf_geekbench_values_file_for_metric "$outdir" "$metric") + avg=$(perf_avg_file_safe "$vf") + if [ -n "$avg" ]; then + perf_geekbench_csv_append "$csv" "$testname" "$metric" "avg" "$avg" "$extra kind=avg" + fi + done <"$metrics_list" + fi + + single_total_avg=$(perf_avg_file_safe "$single_vals") + multi_total_avg=$(perf_avg_file_safe "$multi_vals") + + printf "single_total_avg=%s multi_total_avg=%s\n" "${single_total_avg:-}" "${multi_total_avg:-}" + return 0 +} From 8674a90826568d8b4fb95d796e088685d99fb841 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Mon, 26 Jan 2026 21:12:17 +0530 Subject: [PATCH 2/7] perf(geekbench): implement LAVA-friendly runner with progress + CSV summaries - Add robust init_env discovery and dependency checks - Support wrapper options (runs/outdir/res/bin/core-list/unlock/heartbeat) - Forward unknown args to Geekbench and support raw forwarding via -- - Generate summary/workloads CSV and final readable summary output - Always exit 0 and write PASS/FAIL/SKIP to .res Signed-off-by: Srikanth Muppandam --- Runner/suites/Performance/Geekbench/run.sh | 659 +++++++++++++++++++++ 1 file changed, 659 insertions(+) create mode 100755 Runner/suites/Performance/Geekbench/run.sh diff --git a/Runner/suites/Performance/Geekbench/run.sh b/Runner/suites/Performance/Geekbench/run.sh new file mode 100755 index 00000000..eb41603c --- /dev/null +++ b/Runner/suites/Performance/Geekbench/run.sh @@ -0,0 +1,659 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause-Clear +# Geekbench runner with live console progress + CSV dump (summary + workloads) +# POSIX + LAVA-friendly, always exits 0, writes PASS/FAIL/SKIP to .res + +TESTNAME="Geekbench" + +# ----------------------------------------------------------------------------- +# Robust init_env discovery + load +# ----------------------------------------------------------------------------- +SCRIPT_DIR="$( + cd "$(dirname "$0")" || exit 1 + pwd +)" + +INIT_ENV="" +SEARCH="$SCRIPT_DIR" +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then + INIT_ENV="$SEARCH/init_env" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "${INIT_ENV:-}" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + echo "$TESTNAME SKIP" >"$SCRIPT_DIR/${TESTNAME}.res" 2>/dev/null || true + exit 0 +fi + +if [ -z "${__INIT_ENV_LOADED:-}" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + __INIT_ENV_LOADED=1 +fi + +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/lib_performance.sh" + +# ----------------------------------------------------------------------------- +# Defaults (env vars first, CLI overrides) +# ----------------------------------------------------------------------------- +OUTDIR_DEFAULT="$SCRIPT_DIR/geekbench_out" +RES_FILE_DEFAULT="$SCRIPT_DIR/${TESTNAME}.res" + +RUNS="${GEEKBENCH_RUNS:-1}" +OUTDIR="${GEEKBENCH_OUTDIR:-$OUTDIR_DEFAULT}" +RES_FILE="${GEEKBENCH_RES_FILE:-$RES_FILE_DEFAULT}" +CORE_LIST="${GEEKBENCH_CORE_LIST:-}" +SET_PERF_GOV="${GEEKBENCH_SET_PERF_GOV:-1}" +GB_BIN="${GEEKBENCH_BIN:-geekbench_aarch64}" +PROGRESS_HEARTBEAT_SECS="${GEEKBENCH_PROGRESS_HEARTBEAT_SECS:-15}" + +UNLOCK_EMAIL="${GEEKBENCH_UNLOCK_EMAIL:-}" +UNLOCK_KEY="${GEEKBENCH_UNLOCK_KEY:-}" + +GB_LOAD_FILE="${GEEKBENCH_LOAD_FILE:-}" +GB_SAVE_FILE="${GEEKBENCH_SAVE_FILE:-}" +GB_EXPORT_CSV_FILE="${GEEKBENCH_EXPORT_CSV_FILE:-}" +GB_EXPORT_HTML_FILE="${GEEKBENCH_EXPORT_HTML_FILE:-}" +GB_EXPORT_JSON_FILE="${GEEKBENCH_EXPORT_JSON_FILE:-}" +GB_EXPORT_XML_FILE="${GEEKBENCH_EXPORT_XML_FILE:-}" +GB_EXPORT_TEXT_FILE="${GEEKBENCH_EXPORT_TEXT_FILE:-}" +GB_EXPORT_LICENSE_DIR="${GEEKBENCH_EXPORT_LICENSE_DIR:-}" +GB_UPLOAD="${GEEKBENCH_UPLOAD:-}" +GB_NO_UPLOAD="${GEEKBENCH_NO_UPLOAD:-1}" + +GB_CPU="${GEEKBENCH_CPU:-}" +GB_SYSINFO="${GEEKBENCH_SYSINFO:-}" + +GB_GPU="${GEEKBENCH_GPU:-}" +GB_GPU_LIST="${GEEKBENCH_GPU_LIST:-}" +GB_GPU_PLATFORM_ID="${GEEKBENCH_GPU_PLATFORM_ID:-}" +GB_GPU_DEVICE_ID="${GEEKBENCH_GPU_DEVICE_ID:-}" + +GB_SECTION="${GEEKBENCH_SECTION:-}" +GB_WORKLOAD="${GEEKBENCH_WORKLOAD:-}" +GB_WORKLOAD_LIST="${GEEKBENCH_WORKLOAD_LIST:-}" +GB_SINGLE_CORE="${GEEKBENCH_SINGLE_CORE:-}" +GB_MULTI_CORE="${GEEKBENCH_MULTI_CORE:-}" +GB_CPU_WORKERS="${GEEKBENCH_CPU_WORKERS:-}" +GB_ITERATIONS="${GEEKBENCH_ITERATIONS:-}" +GB_WORKLOAD_GAP="${GEEKBENCH_WORKLOAD_GAP:-}" + +GEEKBENCH_ARGS="${GEEKBENCH_ARGS:-}" + +usage() { + cat <"$RES_FILE" 2>/dev/null || true + exit 0 + ;; + --) IN_FORWARD=1; shift ;; + + --outdir) shift; OUTDIR=${1:-}; shift ;; + --res-file) shift; RES_FILE=${1:-}; shift ;; + --runs) shift; RUNS=${1:-}; shift ;; + --core-list) shift; CORE_LIST=${1:-}; shift ;; + --bin|-bin) shift; GB_BIN=${1:-}; shift ;; + + --unlock) shift; UNLOCK_EMAIL=${1:-}; shift; UNLOCK_KEY=${1:-}; shift ;; + --no-perf-gov) SET_PERF_GOV="0"; shift ;; + --progress-heartbeat) shift; PROGRESS_HEARTBEAT_SECS=${1:-}; shift ;; + + --load) shift; GB_LOAD_FILE=${1:-}; shift ;; + --save) shift; GB_SAVE_FILE=${1:-}; shift ;; + --export-csv) shift; GB_EXPORT_CSV_FILE=${1:-}; shift ;; + --export-html) shift; GB_EXPORT_HTML_FILE=${1:-}; shift ;; + --export-json) shift; GB_EXPORT_JSON_FILE=${1:-}; shift ;; + --export-xml) shift; GB_EXPORT_XML_FILE=${1:-}; shift ;; + --export-text) shift; GB_EXPORT_TEXT_FILE=${1:-}; shift ;; + --export-license) shift; GB_EXPORT_LICENSE_DIR=${1:-}; shift ;; + --upload) GB_UPLOAD=1; GB_NO_UPLOAD=""; shift ;; + --no-upload) GB_NO_UPLOAD=1; GB_UPLOAD=""; shift ;; + --cpu) GB_CPU=1; shift ;; + --sysinfo) GB_SYSINFO=1; shift ;; + + --gpu) + shift + case "${1:-}" in + ""|--*) GB_GPU=1 ;; + *) GB_GPU=$1; shift ;; + esac + ;; + --gpu-list) GB_GPU_LIST=1; shift ;; + --gpu-platform-id) shift; GB_GPU_PLATFORM_ID=${1:-}; shift ;; + --gpu-device-id) shift; GB_GPU_DEVICE_ID=${1:-}; shift ;; + + --section) shift; GB_SECTION=${1:-}; shift ;; + --workload) shift; GB_WORKLOAD=${1:-}; shift ;; + --workload-list) GB_WORKLOAD_LIST=1; shift ;; + --single-core) GB_SINGLE_CORE=1; shift ;; + --multi-core) GB_MULTI_CORE=1; shift ;; + --cpu-workers) shift; GB_CPU_WORKERS=${1:-}; shift ;; + --iterations) shift; GB_ITERATIONS=${1:-}; shift ;; + --workload-gap) shift; GB_WORKLOAD_GAP=${1:-}; shift ;; + + *) append_forward "$1"; shift ;; + esac +done + +# ----------------------------------------------------------------------------- +# Setup +# ----------------------------------------------------------------------------- +mkdir -p "$OUTDIR" 2>/dev/null || true +: >"$RES_FILE" 2>/dev/null || true + +# --------------------------------------------------------------------------- +# Clock sanity (avoid epoch time breaking logs / gating) +# --------------------------------------------------------------------------- +if command -v ensure_reasonable_clock >/dev/null 2>&1; then + log_info "Ensuring system clock is reasonable before Geekbench..." + if ! ensure_reasonable_clock; then + log_error "Clock is not reasonable, Running Geekbench benchmark may lead to invalid results." + fi +else + log_info "ensure_reasonable_clock() not available, continuing without clock sanity check." +fi + +# Warn if RTC is broken (epoch timestamps) +perf_clock_sanity_warn 2>/dev/null || true + +case "${RUNS:-}" in ""|*[!0-9]*) RUNS=1 ;; esac +if [ "$RUNS" -lt 1 ] 2>/dev/null; then RUNS=1; fi + +case "${PROGRESS_HEARTBEAT_SECS:-}" in ""|*[!0-9]*) PROGRESS_HEARTBEAT_SECS=15 ;; esac +if [ "$PROGRESS_HEARTBEAT_SECS" -lt 1 ] 2>/dev/null; then PROGRESS_HEARTBEAT_SECS=15; fi + +SUMMARY_CSV="$OUTDIR/geekbench_summary.csv" +WORKLOADS_CSV="$OUTDIR/geekbench_workloads.csv" +FINAL_SUMMARY_TXT="$OUTDIR/geekbench_final_summary.txt" +HELP_FILE="$OUTDIR/geekbench_help.txt" +UNLOCK_LOG="$OUTDIR/geekbench_unlock.log" + +log_info "Geekbench runner:" +log_info " OUTDIR : $OUTDIR" +log_info " RUNS : $RUNS" +log_info " CORE_LIST : ${CORE_LIST:-none}" +log_info " Requested : $GB_BIN" + +# ----------------------------------------------------------------------------- +# Dependencies +# ----------------------------------------------------------------------------- +if [ -n "${CORE_LIST:-}" ]; then + if ! check_dependencies awk sed grep date mkfifo tee sleep taskset; then + log_skip "$TESTNAME SKIP - missing one or more dependencies" + echo "$TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true + exit 0 + fi +else + if ! check_dependencies awk sed grep date mkfifo tee sleep; then + log_skip "$TESTNAME SKIP - missing one or more dependencies" + echo "$TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true + exit 0 + fi +fi + +# ----------------------------------------------------------------------------- +# Resolve Geekbench binary +# ----------------------------------------------------------------------------- +GB_REAL_BIN=$(perf_geekbench_resolve_bin_and_fix_perms "$GB_BIN" 2>/dev/null || true) +if [ -z "${GB_REAL_BIN:-}" ] || [ ! -x "$GB_REAL_BIN" ]; then + log_skip "$TESTNAME SKIP - geekbench binary not found or not executable" + log_skip " Requested : $GB_BIN" + echo "$TESTNAME SKIP" >"$RES_FILE" 2>/dev/null || true + exit 0 +fi + +log_info "Geekbench:" +log_info " Resolved : $GB_REAL_BIN" + +# ----------------------------------------------------------------------------- +# Optional CPU governor to performance +# ----------------------------------------------------------------------------- +if [ "$SET_PERF_GOV" = "1" ]; then + set_performance_governor || true +fi + +cleanup() { + if [ "$SET_PERF_GOV" = "1" ]; then + restore_governor || true + fi +} +trap cleanup EXIT INT TERM + +# ----------------------------------------------------------------------------- +# Unlock (if requested) then capture --help +# ----------------------------------------------------------------------------- +: >"$HELP_FILE" 2>/dev/null || true + +if [ -n "${UNLOCK_EMAIL:-}" ] && [ -n "${UNLOCK_KEY:-}" ]; then + log_info "Geekbench unlock:" + log_info " Email : (provided)" + log_info " Log : $UNLOCK_LOG" + perf_geekbench_unlock_if_requested "$GB_REAL_BIN" "$UNLOCK_EMAIL" "$UNLOCK_KEY" "$UNLOCK_LOG" || true +fi + +"$GB_REAL_BIN" --help >"$HELP_FILE" 2>&1 || true + +# ----------------------------------------------------------------------------- +# Build Geekbench args (consumes all parsed vars) +# ----------------------------------------------------------------------------- +GB_ARGS_BUILT="" + +# default no-upload +if [ -n "${GB_NO_UPLOAD:-}" ] && [ -z "${GB_UPLOAD:-}" ]; then + if grep -q -- '--no-upload' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --no-upload" + fi +fi + +# cpu/sysinfo +if [ "${GB_CPU:-}" = "1" ] && grep -q -- '--cpu' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --cpu" +fi +if [ "${GB_SYSINFO:-}" = "1" ] && grep -q -- '--sysinfo' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --sysinfo" +fi + +# load/save/export +if [ -n "${GB_LOAD_FILE:-}" ] && grep -q -- '--load' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --load ${GB_LOAD_FILE}" +elif [ -n "${GB_LOAD_FILE:-}" ]; then + log_warn "Geekbench: ignoring unsupported option --load (unlock may be required)" +fi + +if [ -n "${GB_SAVE_FILE:-}" ] && grep -q -- '--save' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --save ${GB_SAVE_FILE}" +elif [ -n "${GB_SAVE_FILE:-}" ]; then + log_warn "Geekbench: ignoring unsupported option --save (unlock may be required)" +fi + +if [ -n "${GB_EXPORT_CSV_FILE:-}" ] && grep -q -- '--export-csv' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --export-csv ${GB_EXPORT_CSV_FILE}" +elif [ -n "${GB_EXPORT_CSV_FILE:-}" ]; then + log_warn "Geekbench: ignoring unsupported option --export-csv (unlock may be required)" +fi + +if [ -n "${GB_EXPORT_HTML_FILE:-}" ] && grep -q -- '--export-html' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --export-html ${GB_EXPORT_HTML_FILE}" +elif [ -n "${GB_EXPORT_HTML_FILE:-}" ]; then + log_warn "Geekbench: ignoring unsupported option --export-html (unlock may be required)" +fi + +if [ -n "${GB_EXPORT_JSON_FILE:-}" ] && grep -q -- '--export-json' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --export-json ${GB_EXPORT_JSON_FILE}" +elif [ -n "${GB_EXPORT_JSON_FILE:-}" ]; then + log_warn "Geekbench: ignoring unsupported option --export-json (unlock may be required)" +fi + +if [ -n "${GB_EXPORT_XML_FILE:-}" ] && grep -q -- '--export-xml' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --export-xml ${GB_EXPORT_XML_FILE}" +elif [ -n "${GB_EXPORT_XML_FILE:-}" ]; then + log_warn "Geekbench: ignoring unsupported option --export-xml (unlock may be required)" +fi + +if [ -n "${GB_EXPORT_TEXT_FILE:-}" ] && grep -q -- '--export-text' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --export-text ${GB_EXPORT_TEXT_FILE}" +elif [ -n "${GB_EXPORT_TEXT_FILE:-}" ]; then + log_warn "Geekbench: ignoring unsupported option --export-text (unlock may be required)" +fi + +if [ -n "${GB_EXPORT_LICENSE_DIR:-}" ] && grep -q -- '--export-license' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --export-license ${GB_EXPORT_LICENSE_DIR}" +elif [ -n "${GB_EXPORT_LICENSE_DIR:-}" ]; then + log_warn "Geekbench: ignoring unsupported option --export-license (unlock may be required)" +fi + +# upload/no-upload +if [ "${GB_UPLOAD:-}" = "1" ]; then + if grep -q -- '--upload' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --upload" + else + log_warn "Geekbench: ignoring unsupported option --upload" + fi +fi +if [ "${GB_NO_UPLOAD:-}" = "1" ] && [ -z "${GB_UPLOAD:-}" ]; then + if grep -q -- '--no-upload' "$HELP_FILE" 2>/dev/null; then + case " $GB_ARGS_BUILT " in + *" --no-upload "*) : ;; + *) GB_ARGS_BUILT="${GB_ARGS_BUILT} --no-upload" ;; + esac + fi +fi + +# gpu +if [ -n "${GB_GPU:-}" ]; then + if grep -q -- '--gpu' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --gpu" + if [ "$GB_GPU" != "1" ] && [ -n "$GB_GPU" ]; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} ${GB_GPU}" + fi + else + log_warn "Geekbench: ignoring unsupported option --gpu" + fi +fi +if [ "${GB_GPU_LIST:-}" = "1" ]; then + if grep -q -- '--gpu-list' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --gpu-list" + else + log_warn "Geekbench: ignoring unsupported option --gpu-list" + fi +fi +if [ -n "${GB_GPU_PLATFORM_ID:-}" ]; then + if grep -q -- '--gpu-platform-id' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --gpu-platform-id ${GB_GPU_PLATFORM_ID}" + else + log_warn "Geekbench: ignoring unsupported option --gpu-platform-id" + fi +fi +if [ -n "${GB_GPU_DEVICE_ID:-}" ]; then + if grep -q -- '--gpu-device-id' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --gpu-device-id ${GB_GPU_DEVICE_ID}" + else + log_warn "Geekbench: ignoring unsupported option --gpu-device-id" + fi +fi + +# pro options +if [ -n "${GB_SECTION:-}" ]; then + if grep -q -- '--section' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --section ${GB_SECTION}" + else + log_warn "Geekbench: ignoring unsupported option --section (unlock required)" + fi +fi +if [ -n "${GB_WORKLOAD:-}" ]; then + if grep -q -- '--workload' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --workload ${GB_WORKLOAD}" + else + log_warn "Geekbench: ignoring unsupported option --workload (unlock required)" + fi +fi +if [ "${GB_WORKLOAD_LIST:-}" = "1" ]; then + if grep -q -- '--workload-list' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --workload-list" + else + log_warn "Geekbench: ignoring unsupported option --workload-list (unlock required)" + fi +fi +if [ "${GB_SINGLE_CORE:-}" = "1" ]; then + if grep -q -- '--single-core' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --single-core" + else + log_warn "Geekbench: ignoring unsupported option --single-core (unlock required)" + fi +fi +if [ "${GB_MULTI_CORE:-}" = "1" ]; then + if grep -q -- '--multi-core' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --multi-core" + else + log_warn "Geekbench: ignoring unsupported option --multi-core (unlock required)" + fi +fi +if [ -n "${GB_CPU_WORKERS:-}" ]; then + if grep -q -- '--cpu-workers' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --cpu-workers ${GB_CPU_WORKERS}" + else + log_warn "Geekbench: ignoring unsupported option --cpu-workers (unlock required)" + fi +fi +if [ -n "${GB_ITERATIONS:-}" ]; then + if grep -q -- '--iterations' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --iterations ${GB_ITERATIONS}" + else + log_warn "Geekbench: ignoring unsupported option --iterations (unlock required)" + fi +fi +if [ -n "${GB_WORKLOAD_GAP:-}" ]; then + if grep -q -- '--workload-gap' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} --workload-gap ${GB_WORKLOAD_GAP}" + else + log_warn "Geekbench: ignoring unsupported option --workload-gap (unlock required)" + fi +fi + +# raw args +if [ -n "${GEEKBENCH_ARGS:-}" ]; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} ${GEEKBENCH_ARGS}" +fi +if [ -n "${FORWARD_ARGS:-}" ]; then + GB_ARGS_BUILT="${GB_ARGS_BUILT} ${FORWARD_ARGS}" +fi + +if [ -z "${GB_ARGS_BUILT# }" ]; then + if grep -q -- '--no-upload' "$HELP_FILE" 2>/dev/null; then + GB_ARGS_BUILT="--no-upload" + else + GB_ARGS_BUILT="" + fi +fi + +log_info "Geekbench args:" +log_info " Built : ${GB_ARGS_BUILT:-}" + +# ----------------------------------------------------------------------------- +# CSV init +# ----------------------------------------------------------------------------- +perf_geekbench_summary_csv_init "$SUMMARY_CSV" +perf_geekbench_workloads_csv_init "$WORKLOADS_CSV" + +# ----------------------------------------------------------------------------- +# Run loop +# ----------------------------------------------------------------------------- +OK_PARSED=0 +any_rc_fail=0 + +i=1 +while [ "$i" -le "$RUNS" ]; do + run_log="$OUTDIR/geekbench_iter${i}.log" + subscores_txt="$OUTDIR/geekbench_iter${i}_subscores.txt" + : >"$run_log" 2>/dev/null || true + : >"$subscores_txt" 2>/dev/null || true + + ts=$(perf_nowstamp_safe) + label="Geekbench run ${i}/${RUNS}" + + log_info "Geekbench run:" + log_info " Run : ${i}/${RUNS}" + log_info " Timestamp : $ts" + log_info " Log : $run_log" + + set -- "$GB_REAL_BIN" + for a in $GB_ARGS_BUILT; do + set -- "$@" "$a" + done + + if [ -n "${CORE_LIST:-}" ]; then + perf_run_cmd_with_progress "$OUTDIR" "$run_log" "$PROGRESS_HEARTBEAT_SECS" "$label" -- \ + taskset -c "$CORE_LIST" "$@" + else + perf_run_cmd_with_progress "$OUTDIR" "$run_log" "$PROGRESS_HEARTBEAT_SECS" "$label" -- \ + "$@" + fi + + rc=$? + if [ "$rc" -ne 0 ]; then + any_rc_fail=1 + log_warn "Geekbench run failed: iter, $i, rc, $rc" + fi + + # workloads -> file + console (lib helper, no awk here) + perf_geekbench_write_iter_subscores_txt "$run_log" "$subscores_txt" || true + if [ -s "$subscores_txt" ]; then + log_info "Geekbench sub-benchmarks:" + log_info " File : $subscores_txt" + perf_geekbench_log_subscores_file "$subscores_txt" || true + else + log_info "Geekbench sub-benchmarks: Not found (sysinfo/gpu-list/load is ok)" + fi + + # summary parse + if perf_geekbench_has_benchmark_summary "$run_log"; then + scoreline=$(perf_parse_geekbench_summary_scores "$run_log") + if [ -n "${scoreline:-}" ]; then + # shellcheck disable=SC2046 + eval "$(perf_geekbench_scores_to_vars "$scoreline")" + + printf '%s,%s,%s,%s,%s,%s,%s,%s,%s\n' \ + "$ts" "$TESTNAME" "$i" "${st:-}" "${si:-}" "${sf:-}" "${mt:-}" "${mi:-}" "${mf:-}" \ + >>"$SUMMARY_CSV" 2>/dev/null || true + + perf_append_geekbench_workloads_csv "$run_log" "$ts" "$TESTNAME" "$i" "$WORKLOADS_CSV" + perf_geekbench_log_summary_scores "${st:-}" "${si:-}" "${sf:-}" "${mt:-}" "${mi:-}" "${mf:-}" + + parsed_any=0 + if [ -n "${st:-}" ] && perf_is_number_safe "$st"; then parsed_any=1; fi + if [ -n "${mt:-}" ] && perf_is_number_safe "$mt"; then parsed_any=1; fi + if [ "$parsed_any" -eq 1 ]; then OK_PARSED=1; fi + else + log_warn "Geekbench summary present but totals not parsed" + fi + else + log_info "Geekbench summary: Not found (sysinfo/gpu-list/load is ok)" + fi + + i=$((i + 1)) +done + +# ----------------------------------------------------------------------------- +# Final summary (avg across parsed rows) +# ----------------------------------------------------------------------------- +avg_st=$(awk -F',' 'NR>1 && $4 ~ /^[0-9]+$/ {n++; s+=$4} END{if(n>0) printf "%.0f", s/n}' "$SUMMARY_CSV" 2>/dev/null) +avg_si=$(awk -F',' 'NR>1 && $5 ~ /^[0-9]+$/ {n++; s+=$5} END{if(n>0) printf "%.0f", s/n}' "$SUMMARY_CSV" 2>/dev/null) +avg_sf=$(awk -F',' 'NR>1 && $6 ~ /^[0-9]+$/ {n++; s+=$6} END{if(n>0) printf "%.0f", s/n}' "$SUMMARY_CSV" 2>/dev/null) +avg_mt=$(awk -F',' 'NR>1 && $7 ~ /^[0-9]+$/ {n++; s+=$7} END{if(n>0) printf "%.0f", s/n}' "$SUMMARY_CSV" 2>/dev/null) +avg_mi=$(awk -F',' 'NR>1 && $8 ~ /^[0-9]+$/ {n++; s+=$8} END{if(n>0) printf "%.0f", s/n}' "$SUMMARY_CSV" 2>/dev/null) +avg_mf=$(awk -F',' 'NR>1 && $9 ~ /^[0-9]+$/ {n++; s+=$9} END{if(n>0) printf "%.0f", s/n}' "$SUMMARY_CSV" 2>/dev/null) + +: >"$FINAL_SUMMARY_TXT" 2>/dev/null || true +perf_write_and_log "$FINAL_SUMMARY_TXT" "Geekbench Summary" +perf_write_and_log "$FINAL_SUMMARY_TXT" " timestamp, $(perf_nowstamp_safe)" +perf_write_and_log "$FINAL_SUMMARY_TXT" " outdir, $OUTDIR" +perf_write_and_log "$FINAL_SUMMARY_TXT" " runs, $RUNS" +perf_write_and_log "$FINAL_SUMMARY_TXT" " core_list, ${CORE_LIST:-none}" +perf_write_and_log "$FINAL_SUMMARY_TXT" " bin, $GB_REAL_BIN" +perf_write_and_log "$FINAL_SUMMARY_TXT" " args, ${GB_ARGS_BUILT:-}" +perf_write_and_log "$FINAL_SUMMARY_TXT" "" +perf_write_and_log "$FINAL_SUMMARY_TXT" "CSV outputs" +perf_write_and_log "$FINAL_SUMMARY_TXT" " summary_csv, $SUMMARY_CSV" +perf_write_and_log "$FINAL_SUMMARY_TXT" " workloads_csv, $WORKLOADS_CSV" +perf_write_and_log "$FINAL_SUMMARY_TXT" "" + +if [ -n "${avg_st:-}" ] || [ -n "${avg_mt:-}" ]; then + perf_write_and_log "$FINAL_SUMMARY_TXT" "Benchmark Summary, average over parsed runs" + [ -n "${avg_st:-}" ] && perf_write_and_log "$FINAL_SUMMARY_TXT" " Single-Core Score, $avg_st" + [ -n "${avg_si:-}" ] && perf_write_and_log "$FINAL_SUMMARY_TXT" " Single-Core Integer Score, $avg_si" + [ -n "${avg_sf:-}" ] && perf_write_and_log "$FINAL_SUMMARY_TXT" " Single-Core Floating Point Score, $avg_sf" + [ -n "${avg_mt:-}" ] && perf_write_and_log "$FINAL_SUMMARY_TXT" " Multi-Core Score, $avg_mt" + [ -n "${avg_mi:-}" ] && perf_write_and_log "$FINAL_SUMMARY_TXT" " Multi-Core Integer Score, $avg_mi" + [ -n "${avg_mf:-}" ] && perf_write_and_log "$FINAL_SUMMARY_TXT" " Multi-Core Floating Point Score, $avg_mf" +else + perf_write_and_log "$FINAL_SUMMARY_TXT" "Benchmark Summary, not available, no parsed Benchmark Summary across runs" + perf_write_and_log "$FINAL_SUMMARY_TXT" "This is expected for sysinfo, gpu-list, load" +fi + +# ----------------------------------------------------------------------------- +# PASS/FAIL +# ----------------------------------------------------------------------------- +status="FAIL" +if [ "$OK_PARSED" -eq 1 ]; then + status="PASS" +else + if [ "$any_rc_fail" -eq 0 ]; then + status="PASS" + fi +fi + +if [ "$status" = "PASS" ]; then + log_pass "$TESTNAME PASS" + echo "$TESTNAME PASS" >"$RES_FILE" 2>/dev/null || true +else + log_fail "$TESTNAME FAIL, see logs in, $OUTDIR" + echo "$TESTNAME FAIL" >"$RES_FILE" 2>/dev/null || true +fi + +exit 0 From 329da36323ebe064340d95166ea4902ac82d7743 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Mon, 26 Jan 2026 21:13:34 +0530 Subject: [PATCH 3/7] lava(geekbench): add job template to run Geekbench suite and collect artifacts - Run Geekbench runner from qcom-linux-testkit - Publish logs, CSV outputs, and final summary as test artifacts - Keep template generic for RB3/RB4/RB8 targets Signed-off-by: Srikanth Muppandam --- .../Geekbench/geekbench-performance.yaml | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100755 Runner/suites/Performance/Geekbench/geekbench-performance.yaml diff --git a/Runner/suites/Performance/Geekbench/geekbench-performance.yaml b/Runner/suites/Performance/Geekbench/geekbench-performance.yaml new file mode 100755 index 00000000..c1b2fb1f --- /dev/null +++ b/Runner/suites/Performance/Geekbench/geekbench-performance.yaml @@ -0,0 +1,117 @@ +metadata: + name: geekbench-performance + format: "Lava-Test Test Definition 1.0" + description: > + Geekbench 6 CPU performance runner with live console progress, per-iteration logs, + readable CSV dumps (summary + workloads), and optional full metrics CSV. + Designed for Yocto / LE platforms. LAVA-friendly runner (does not hard-fail the job). + os: + - linux + scope: + - performance + - functional + +params: + # Output + OUT_DIR: "./logs_Geekbench" + RES_FILE: "" # optional, defaults to Geekbench.res in suite dir + + # Outer loop (how many times run.sh invokes geekbench) + RUNS: "1" + + # Progress heartbeat + HEARTBEAT_SECS: "15" + + # Optional pinning + CORE_LIST: "" # e.g. "0-3" or "0,2,4,6" + + # Environment/stability + SET_PERF_GOV: "1" + + # Geekbench binary override (else run.sh auto-detects) + GEEKBENCH_BIN: "geekbench_aarch64" + + # Unlock (optional) + UNLOCK_EMAIL: "" + UNLOCK_KEY: "" + + # Upload policy + NO_UPLOAD: "1" + UPLOAD: "0" + + # Actions / modes (leave empty to run default CPU benchmark) + CPU: "1" + SYSINFO: "0" + + # GPU (optional) + GPU: "" # "" or "1" or "OpenCL" + GPU_LIST: "0" + GPU_PLATFORM_ID: "" + GPU_DEVICE_ID: "" + + # Pro options (optional) + SECTION: "" # e.g. "1" or "1,2" or "1-3" + WORKLOAD: "" # e.g. "1,4,7" or "1-10" + WORKLOAD_LIST: "0" + SINGLE_CORE: "0" + MULTI_CORE: "0" + CPU_WORKERS: "" # e.g. "8" + GB_ITERATIONS: "" # geekbench internal --iterations + WORKLOAD_GAP: "" # ms gap between workloads + + # Export options (optional) + LOAD_FILE: "" + SAVE_FILE: "" + EXPORT_CSV_FILE: "" + EXPORT_HTML_FILE: "" + EXPORT_JSON_FILE: "" + EXPORT_XML_FILE: "" + EXPORT_TEXT_FILE: "" + EXPORT_LICENSE_DIR: "" + + # Raw extra args appended as-is (space-separated) + EXTRA_ARGS: "" + + # Standalone mode (no init_env) if your run.sh supports it + STANDALONE: "0" + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Performance/Geekbench/ || exit 0 + - ./run.sh + --outdir "$OUT_DIR" + --res-file "${RES_FILE:-}" + --runs "$RUNS" + --core-list "${CORE_LIST:-}" + --bin "$GEEKBENCH_BIN" + --progress-heartbeat "$HEARTBEAT_SECS" + $( [ "$SET_PERF_GOV" = "1" ] && true || echo --no-perf-gov ) + $( [ "$NO_UPLOAD" = "1" ] && echo --no-upload || true ) + $( [ "$UPLOAD" = "1" ] && echo --upload || true ) + $( [ "$CPU" = "1" ] && echo --cpu || true ) + $( [ "$SYSINFO" = "1" ] && echo --sysinfo || true ) + $( [ -n "$GPU" ] && echo --gpu "$GPU" || true ) + $( [ "$GPU_LIST" = "1" ] && echo --gpu-list || true ) + $( [ -n "$GPU_PLATFORM_ID" ] && echo --gpu-platform-id "$GPU_PLATFORM_ID" || true ) + $( [ -n "$GPU_DEVICE_ID" ] && echo --gpu-device-id "$GPU_DEVICE_ID" || true ) + $( [ -n "$SECTION" ] && echo --section "$SECTION" || true ) + $( [ -n "$WORKLOAD" ] && echo --workload "$WORKLOAD" || true ) + $( [ "$WORKLOAD_LIST" = "1" ] && echo --workload-list || true ) + $( [ "$SINGLE_CORE" = "1" ] && echo --single-core || true ) + $( [ "$MULTI_CORE" = "1" ] && echo --multi-core || true ) + $( [ -n "$CPU_WORKERS" ] && echo --cpu-workers "$CPU_WORKERS" || true ) + $( [ -n "$GB_ITERATIONS" ] && echo --iterations "$GB_ITERATIONS" || true ) + $( [ -n "$WORKLOAD_GAP" ] && echo --workload-gap "$WORKLOAD_GAP" || true ) + $( [ -n "$LOAD_FILE" ] && echo --load "$LOAD_FILE" || true ) + $( [ -n "$SAVE_FILE" ] && echo --save "$SAVE_FILE" || true ) + $( [ -n "$EXPORT_CSV_FILE" ] && echo --export-csv "$EXPORT_CSV_FILE" || true ) + $( [ -n "$EXPORT_HTML_FILE" ] && echo --export-html "$EXPORT_HTML_FILE" || true ) + $( [ -n "$EXPORT_JSON_FILE" ] && echo --export-json "$EXPORT_JSON_FILE" || true ) + $( [ -n "$EXPORT_XML_FILE" ] && echo --export-xml "$EXPORT_XML_FILE" || true ) + $( [ -n "$EXPORT_TEXT_FILE" ] && echo --export-text "$EXPORT_TEXT_FILE" || true ) + $( [ -n "$EXPORT_LICENSE_DIR" ] && echo --export-license "$EXPORT_LICENSE_DIR" || true ) + $( [ -n "$UNLOCK_EMAIL" ] && [ -n "$UNLOCK_KEY" ] && echo --unlock "$UNLOCK_EMAIL" "$UNLOCK_KEY" || true ) + -- ${EXTRA_ARGS:-} + || true + - $REPO_PATH/Runner/utils/send-to-lava.sh Geekbench.res From 94e7857f8d6591d5a94271cb0625b46b2ab0c681 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Mon, 26 Jan 2026 21:14:09 +0530 Subject: [PATCH 4/7] Yaml file for Geekbench single-core Signed-off-by: Srikanth Muppandam --- .../Geekbench/geekbench-cpu-single.yaml | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 Runner/suites/Performance/Geekbench/geekbench-cpu-single.yaml diff --git a/Runner/suites/Performance/Geekbench/geekbench-cpu-single.yaml b/Runner/suites/Performance/Geekbench/geekbench-cpu-single.yaml new file mode 100755 index 00000000..ca3c4fad --- /dev/null +++ b/Runner/suites/Performance/Geekbench/geekbench-cpu-single.yaml @@ -0,0 +1,53 @@ +metadata: + name: geekbench-cpu-single + format: "Lava-Test Test Definition 1.0" + description: > + Geekbench 6 CPU single-core only run (single-thread workloads) with live progress, + per-iteration logs and CSV dumps. + os: + - linux + scope: + - performance + - functional + +params: + OUT_DIR: "./logs_Geekbench_Single" + RUNS: "1" + HEARTBEAT_SECS: "15" + CORE_LIST: "" + SET_PERF_GOV: "1" + GEEKBENCH_BIN: "geekbench_aarch64" + + NO_UPLOAD: "1" + UPLOAD: "0" + + # Geekbench internal options + GB_ITERATIONS: "" # geekbench --iterations (internal) + WORKLOAD_GAP: "" # ms + + # Export options (optional) + EXPORT_TEXT_FILE: "" # if set, geekbench will write it too (script will still parse logs) + + EXTRA_ARGS: "" + STANDALONE: "0" + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Performance/Geekbench/ || exit 0 + - ./run.sh + --outdir "$OUT_DIR" + --runs "$RUNS" + --core-list "${CORE_LIST:-}" + --bin "$GEEKBENCH_BIN" + --progress-heartbeat "$HEARTBEAT_SECS" + $( [ "$SET_PERF_GOV" = "1" ] && true || echo --no-perf-gov ) + $( [ "$NO_UPLOAD" = "1" ] && echo --no-upload || true ) + $( [ "$UPLOAD" = "1" ] && echo --upload || true ) + --cpu + --single-core + $( [ -n "$GB_ITERATIONS" ] && echo --iterations "$GB_ITERATIONS" || true ) + $( [ -n "$WORKLOAD_GAP" ] && echo --workload-gap "$WORKLOAD_GAP" || true ) + $( [ -n "$EXPORT_TEXT_FILE" ] && echo --export-text "$EXPORT_TEXT_FILE" || true ) + -- ${EXTRA_ARGS:-} || true + - $REPO_PATH/Runner/utils/send-to-lava.sh Geekbench.res From 49380994c9ca7c3adb5fc446c2ee83e4e2eca79f Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Mon, 26 Jan 2026 21:14:32 +0530 Subject: [PATCH 5/7] Yaml file for Geekbench multi-core Signed-off-by: Srikanth Muppandam --- .../Geekbench/geekbench-cpu-multi.yaml | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100755 Runner/suites/Performance/Geekbench/geekbench-cpu-multi.yaml diff --git a/Runner/suites/Performance/Geekbench/geekbench-cpu-multi.yaml b/Runner/suites/Performance/Geekbench/geekbench-cpu-multi.yaml new file mode 100755 index 00000000..16032370 --- /dev/null +++ b/Runner/suites/Performance/Geekbench/geekbench-cpu-multi.yaml @@ -0,0 +1,55 @@ +metadata: + name: geekbench-cpu-multi + format: "Lava-Test Test Definition 1.0" + description: > + Geekbench 6 CPU multi-core only run (multi-thread workloads) with live progress, + per-iteration logs and CSV dumps. Supports cpu-workers control. + os: + - linux + scope: + - performance + - functional + +params: + OUT_DIR: "./logs_Geekbench_Multi" + RUNS: "1" + HEARTBEAT_SECS: "15" + CORE_LIST: "" + SET_PERF_GOV: "1" + GEEKBENCH_BIN: "geekbench_aarch64" + + NO_UPLOAD: "1" + UPLOAD: "0" + + # Multi-core controls + CPU_WORKERS: "" # e.g. "8" (if empty, Geekbench defaults) + GB_ITERATIONS: "" # geekbench --iterations (internal) + WORKLOAD_GAP: "" # ms + + EXPORT_TEXT_FILE: "" + EXTRA_ARGS: "" + STANDALONE: "0" + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Performance/Geekbench/ || exit 0 + - ./run.sh + --outdir "$OUT_DIR" + --runs "$RUNS" + --core-list "${CORE_LIST:-}" + --bin "$GEEKBENCH_BIN" + --progress-heartbeat "$HEARTBEAT_SECS" + $( [ "$SET_PERF_GOV" = "1" ] && true || echo --no-perf-gov ) + $( [ "$NO_UPLOAD" = "1" ] && echo --no-upload || true ) + $( [ "$UPLOAD" = "1" ] && echo --upload || true ) + --cpu + --multi-core + $( [ -n "$CPU_WORKERS" ] && echo --cpu-workers "$CPU_WORKERS" || true ) + $( [ -n "$GB_ITERATIONS" ] && echo --iterations "$GB_ITERATIONS" || true ) + $( [ -n "$WORKLOAD_GAP" ] && echo --workload-gap "$WORKLOAD_GAP" || true ) + $( [ -n "$EXPORT_TEXT_FILE" ] && echo --export-text "$EXPORT_TEXT_FILE" || true ) + -- ${EXTRA_ARGS:-} + || true + + - $REPO_PATH/Runner/utils/send-to-lava.sh Geekbench.res From bbcf4b9bff786396361d304c6a2415cca7cbed17 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Mon, 26 Jan 2026 21:15:06 +0530 Subject: [PATCH 6/7] perf(geekbench): add config defaults for runs, pinning, and output paths - Provide reproducible defaults for iterations and output directory - Allow optional CPU pinning and wrapper env overrides - Document knobs used by LAVA and local runs Signed-off-by: Srikanth Muppandam --- .../Geekbench/geekbench_baseline.conf | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 Runner/suites/Performance/Geekbench/geekbench_baseline.conf diff --git a/Runner/suites/Performance/Geekbench/geekbench_baseline.conf b/Runner/suites/Performance/Geekbench/geekbench_baseline.conf new file mode 100755 index 00000000..b81e0c6e --- /dev/null +++ b/Runner/suites/Performance/Geekbench/geekbench_baseline.conf @@ -0,0 +1,71 @@ +# geekbench_baseline.conf +# +# Geekbench 6 baseline / gating config for Geekbench +# - Designed to be simple + human-editable (same spirit as your tiotest baseline) +# - Use with your runner's --baseline / --delta logic (PASS/FAIL vs thresholds) +# +# Units: +# - Summary scores are plain integers (Geekbench score) +# - Workload throughput targets use the unit Geekbench prints (e.g., MB/sec) +# +# Tips: +# - Start with summary-only gating (recommended) +# - Add per-workload goals only when your platform is stable enough +# - Keep goals realistic; use DELTA (allowed deviation) from YAML to avoid flakiness +# +# ------------------------------------------------------------------------------ +# Summary score gating (recommended) +# ------------------------------------------------------------------------------ + +# Minimum acceptable Geekbench summary totals (avg across iterations) +# If these are present, runner should enforce: +# measured >= goal * (1 - delta) +goal.geekbench.summary.single.total_score = 1165 +goal.geekbench.summary.multi.total_score = 2881 + +# Optional: sub-scores (enable if you want tighter gating) +#goal.geekbench.summary.single.integer_score = 1195 +#goal.geekbench.summary.single.floating_point_score = 1111 +#goal.geekbench.summary.multi.integer_score = 2806 +#goal.geekbench.summary.multi.floating_point_score = 3025 + +# ------------------------------------------------------------------------------ +# Optional per-workload gating (advanced) +# ------------------------------------------------------------------------------ +# NOTE: +# - Workloads are sectioned by single/multi +# - You can gate on "score" (integer) or "throughput" (float) separately +# +# Naming convention (matches long-metric key style): +# goal.geekbench.
.workload.. +# where: +# section = single | multi +# kind = score | throughput +# +# WorkloadName must match Geekbench output text exactly (case/spaces). +# If your implementation sanitizes names, mirror that same sanitization here. + +# ---- Single-Core (examples from your sample output) ---- +#goal.geekbench.single.workload.File Compression.score = 1091 +#goal.geekbench.single.workload.File Compression.throughput = 156.6 +#goal.geekbench.single.workload.Navigation.score = 1152 +#goal.geekbench.single.workload.Navigation.throughput = 6.94 +#goal.geekbench.single.workload.HTML5 Browser.score = 1264 +#goal.geekbench.single.workload.HTML5 Browser.throughput = 25.9 + +# ---- Multi-Core (examples from your sample output) ---- +#goal.geekbench.multi.workload.File Compression.score = 1317 +#goal.geekbench.multi.workload.File Compression.throughput = 189.2 +#goal.geekbench.multi.workload.PDF Renderer.score = 4918 +#goal.geekbench.multi.workload.PDF Renderer.throughput = 113.4 +#goal.geekbench.multi.workload.Clang.score = 4249 +#goal.geekbench.multi.workload.Clang.throughput = 20.9 + +# ------------------------------------------------------------------------------ +# Optional metadata (ignored by gating, useful for humans/tools) +# ------------------------------------------------------------------------------ + +#platform = RB3gen2 +#os = "QCOM Reference Distro with Wayland 2.0" +#kernel = "Linux 6.19.0-rc4-00414-g65bb05266d47 aarch64" +#notes = "Baseline captured with --no-upload, default CPU benchmark" From 054399570ece0cdb70b0c660fbf993a2459ea6f8 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Mon, 26 Jan 2026 21:15:41 +0530 Subject: [PATCH 7/7] docs(geekbench): document usage, forwarding rules, and output artifacts - Explain wrapper options vs forwarded Geekbench args - Add examples for single/multi-core, runs, and taskset pinning - Document generated logs/CSVs and .res semantics for LAVA Signed-off-by: Srikanth Muppandam --- .../Performance/Geekbench/README_Geekbench.md | 427 ++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 Runner/suites/Performance/Geekbench/README_Geekbench.md diff --git a/Runner/suites/Performance/Geekbench/README_Geekbench.md b/Runner/suites/Performance/Geekbench/README_Geekbench.md new file mode 100644 index 00000000..24643215 --- /dev/null +++ b/Runner/suites/Performance/Geekbench/README_Geekbench.md @@ -0,0 +1,427 @@ +# Geekbench Performance (Geekbench) + +This suite runs **Geekbench 6** on embedded Linux targets (Yocto / LE / Ubuntu variants) and produces: +- **Live console progress** (workload-by-workload + heartbeat) +- **Per-iteration logs** +- **CSV outputs** (readable summary + workloads, and optional “all metrics” long format) +- **LAVA-friendly result** file (`Geekbench.res`) with PASS/FAIL/SKIP + +It is designed to work inside the **qcom-linux-testkit** Runner layout and to be overridden from **LAVA YAML params** as well as **script CLI args**. + +--- + +## Contents + +- [What this suite does](#what-this-suite-does) +- [Prerequisites](#prerequisites) +- [Where to place Geekbench](#where-to-place-geekbench) +- [License and unlocking](#license-and-unlocking) +- [Outputs](#outputs) +- [Running locally](#running-locally) +- [LAVA integration](#lava-integration) +- [All supported Geekbench options](#all-supported-geekbench-options) +- [Runner options and environment variables](#runner-options--environment-variables) +- [Examples](#examples) +- [Baseline / gating (.conf)](#baseline--gating-conf) +- [Troubleshooting](#troubleshooting) + +--- + +## What this suite does + +By default, Geekbench runs the **CPU benchmark**. This runner: +1. Detects `init_env` and loads `functestlib.sh` + `lib_performance.sh`. +2. Optionally forces CPU governors to `performance` (best-effort). +3. Runs Geekbench **N times** (`RUNS` / `--runs`) with **live progress**: + - raw Geekbench output is streamed to console + - progress lines are emitted as `log_info`: + - `Progress,