Skip to content

feat(benchmarks): macOS benchmark suite + fresh-install and review fixes#53

Merged
ulises-c merged 10 commits into
mainfrom
feat/packages-macos-benchmarks
Jul 1, 2026
Merged

feat(benchmarks): macOS benchmark suite + fresh-install and review fixes#53
ulises-c merged 10 commits into
mainfrom
feat/packages-macos-benchmarks

Conversation

@ulises-c

@ulises-c ulises-c commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a macOS benchmarking suite and integrates its tooling into the installer, then hardens it against a round of fresh-install feedback and a max-effort code review.

Benchmark suite (macOS/benchmarks/): benchmark.sh (CPU/memory/storage/GPU), stress-test.sh (sustained load + throttle detection), llm-bench.sh (MLX + llama.cpp), omlx-bench.sh (concurrency sweep), standardized.sh (Geekbench 6 / Geekbench AI / Cinebench / Blender wrappers), plus compare.sh, collect-sysinfo.sh, and shared lib.sh. New benchmarking tag category in packages.json.

Fresh-install fixes (e60aa79):

  • Prime sudo once with a background keepalive so cask/pkg installers stop prompting ~6 times.
  • Resolve the oMLX DMG by macOS generation instead of blindly taking the first asset.
  • Stop auto-running the (upstream-buggy) codeburn menubar; print it as a manual step.
  • Add [i/N] progress counters to the brew/cask/pipx install tiers.
  • Install Cinebench from Maxon's .dmg (custom) instead of the brew cask, whose pinned checksum goes stale against Maxon's rolling build.

Review-finding fixes (3cba935):

  • standardized.sh: Blender guard [[ … && ! $CPU_ONLY ]] was always false (string negation) so Blender never ran — corrected to && ! $CPU_ONLY.
  • benchmark.sh: fio scratch trap … RETURNEXIT (RETURN never fires at script scope, leaking a multi-GB dir); guard empty openssl parse → 0.
  • stress-test.sh: floor SAMPLE_COUNT to ≥1 (short duration divided by zero); die on empty/zero baseline; guard empty per-sample throughput.
  • standardized.sh: capture ts_file once so OUTFILE/RAWDIR can't straddle a second boundary.
  • omlx-bench.sh: now_s() falls back to date +%s when perl is absent; print n/a instead of 0.0 when there is no single-stream sample.
  • llm-bench.sh: .avg_ts | tonumber? so a null row can't abort the run under set -e.
  • platforms/macos.sh: gate mac_custom_install_tier on handled_by_setup, matching the documented custom-manager contract.
  • install-omlx-app.sh: pick the DMG whose macosNN is the highest ≤ this Mac's major version (was hardcoded 26/27, fell through on 28+).
  • New macOS/lib-dmg-install.sh: shared DMG download/mount/copy helper sourced by both installers; trap bakes paths in at register time so EXIT cleanup works under set -u.
  • lib.sh: drop unused check_dep_optional.

Test plan

  • shellcheck --severity=warning clean on all shell scripts.
  • scripts/validate-packages.sh PASSED (105 entries).
  • scripts/dryrun-smoke.sh PASSED — setup.sh --dry-run clean on macos/ubuntu/arch/server.
  • Behavioral checks (bash/jq): oMLX version selection across macOS 14–28, set -e safety of the arithmetic guards, Blender truth table, tonumber? null-dropping, and the DMG-helper EXIT-trap under set -u.

Caveat: the benchmark scripts themselves have not been run live on a Mac (no hdiutil/openssl speed/powermetrics in CI). The LibreSSL openssl speed column question is now safely guarded (empty → 0/die) but not yet confirmed against a real run.

🤖 Generated with Claude Code

ulises-c and others added 5 commits June 26, 2026 03:27
Add macOS/benchmarks/ with synthetic CPU/memory/storage benchmarks, a
thermal stress/throttle test, standardized benchmark wrappers (Geekbench
6, Cinebench, Blender), a local-LLM benchmark across MLX and llama.cpp,
and an oMLX continuous-batching concurrency benchmark. A suite-aware
compare.sh diffs two machines' results.

Wire new optional macOS tools into packages.json (fio, hyperfine,
stress-ng, geekbench, cinebench, blender-benchmark) and install the oMLX
menu-bar app from its GitHub .dmg via macOS/install-omlx-app.sh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wrap the Geekbench AI `banff` CLI (--ai) in standardized.sh alongside
Geekbench 6/Cinebench/Blender, recording the result URL (free CLI uploads
to the Geekbench AI Browser). Add the geekbench-ai cask to packages.json
and a Geekbench AI score row to compare.sh.

Document that oMLX's built-in /admin benchmark (performance + intelligence)
is dashboard-only; omlx-bench.sh is the scriptable counterpart for the
performance (PP/TG tokens/sec) side.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add "benchmarking" to the controlled tag vocabulary in
scripts/validate-packages.sh and retag the benchmark/stress-test tools
(fio, hyperfine, stress-ng, geekbench, geekbench-ai, cinebench,
blender-benchmark) from system-monitoring to benchmarking. The
interactive selector picks it up automatically (vocabulary is derived
from packages.json), so `--tags benchmarking` installs just these.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Prime sudo once with a background keepalive so cask/pkg installers
  reuse the cached credential instead of prompting ~6 times.
- Resolve the oMLX DMG by macOS generation (macos15-sequoia vs
  macos26-27) via sw_vers instead of blindly taking head -1.
- Stop auto-running `codeburn menubar` (buggy upstream); print it as a
  manual post-install step. codeburn itself still installs.
- Add [i/N] progress counters to brew, cask, and pipx install tiers.
- Install cinebench from Maxon's .dmg (custom) instead of the brew cask,
  whose pinned checksum goes stale against Maxon's rolling build
  (SHA256 mismatch). Update the two stale cask references in the docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Correctness:
- standardized.sh: Blender guard `[[ ... && ! $CPU_ONLY ]]` was always
  false (string negation) so Blender never ran; use `&& ! $CPU_ONLY`.
- benchmark.sh: fio scratch trap RETURN → EXIT (RETURN never fires at
  script scope, leaking a multi-GB dir); guard empty openssl parse → 0.
- stress-test.sh: floor SAMPLE_COUNT to ≥1 (short DURATION divided by
  zero); die on empty/zero baseline; guard empty per-sample throughput.
- standardized.sh: capture ts_file once so OUTFILE/RAWDIR can't straddle
  a second boundary and mismatch.
- omlx-bench.sh: now_s() falls back to `date +%s` when perl is absent so
  jq -n interpolation never gets an empty operand; print "n/a" instead of
  0.0 when there is no single-stream sample.
- llm-bench.sh: `.avg_ts | tonumber?` so a null row can't abort the run.
- platforms/macos.sh: gate mac_custom_install_tier on handled_by_setup,
  matching the documented custom-manager contract.

Altitude / cleanup:
- install-omlx-app.sh: pick the DMG whose macosNN is the highest ≤ this
  Mac's major version (was hardcoded 26/27, fell through on 28+).
- lib-dmg-install.sh: extract the shared DMG download/mount/copy helper;
  both installers source it. Trap bakes paths in at register time so the
  EXIT cleanup works under set -u after the function returns.
- lib.sh: drop unused check_dep_optional.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ulises-c ulises-c changed the title feat(benchmarks): macOS benchmark, stress, LLM & oMLX suites feat(benchmarks): macOS benchmark suite + fresh-install and review fixes Jul 1, 2026
ulises-c and others added 5 commits July 1, 2026 14:10
…ndings

Full-branch max-effort review (10 finder angles + per-finding verification
+ gap sweep) of the macOS benchmark suite. P0: broken measurement paths
(LibreSSL -seconds, llama-bench --hf-repo, GPU/mem-bw/powermetrics parses,
Cinebench find depth), data corruption (compare.sh crash, omlx silent
request failures, Cinebench single-core bleed), setup aborts, and a
public-repo hostname leak. P1/P2: moderate and latent correctness. P3:
dedupe cleanups.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- lib.sh: resolve_openssl picks brew openssl@3 / real OpenSSL — stock
  LibreSSL lacks `speed -seconds`; all speed substitutions now || true
- benchmark.sh: drop the GPU section (llm-bench.sh owns tokens/s with a
  pinned model); anchor the stress-ng stream parse on the metrc row
- llm-bench.sh: llama-bench takes no --hf-repo — resolve the quant's
  .gguf via the HF API, cache it, pass -m; keep stderr for diagnostics
- standardized.sh: -maxdepth 4 so the Cinebench binary is findable;
  separate raw files per Cinebench pass (no multi→single score bleed);
  run single-core under --cpu-only (it is a CPU test); download the
  Blender runtime + scenes before benchmarking
- stress-test.sh: baseline measured under load after clocks settle
  (idle baseline read contention as throttling); Apple Silicon
  powermetrics patterns (HW active frequency / CPU Power, mW→W)
- compare.sh: null pct renders n/a instead of crashing the table
  (@TSV empty-field collapse under IFS tab); add the stress suite;
  header comment lists all five suites
- omlx-bench.sh: fire_one reports failures; per-level failed_requests
  recorded; failed levels excluded from peak/speedup
- platforms/macos.sh: custom tier collects failures like the brew
  tiers instead of aborting the remaining setup run under set -e
- lib/verify.sh: macOS custom probe also checks /Applications .app
  bundles so cinebench/omlx verify after install
- README: placeholder hostnames + correct results path in the compare
  example; docs updated for openssl@3, GGUF cache, loaded baseline

Validated: shellcheck + bash -n clean, dryrun-smoke passes all four
platforms, compare.sh crash/stress paths exercised with fixture files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- llm-bench.sh: guard the MLX PP/TG/MEM parse pipelines with || true so
  stats-format drift records null instead of dying under pipefail
- stress-test.sh / omlx-bench.sh: INT/TERM traps now exit (cleanup runs
  once via the EXIT trap) — a mid-run kill previously stopped the load
  but kept sampling an idle machine and wrote a bogus throttled:false
  result; verified with a PID-directed kill test
- omlx-bench.sh: pass --port to `omlx serve` so an OMLX_PORT override
  polls the port the server actually binds
- lib.sh: ensure_results_dir chowns results/ to SUDO_USER so a sudo
  stress-test run doesn't make every later non-sudo suite die at its
  final result write
- compare.sh: metrics measured on only one machine render Win=n/a and
  stay out of the A/B win tally; drop the Geekbench AI row (the free
  CLI never yields a numeric score, only a browser URL)
- benchmark.sh: scaling_factor via --argjson — a real number (or null)
  in the result JSON instead of a string

Validated: shellcheck + bash -n clean; compare.sh fixture run shows the
one-sided row as n/a and excluded from the tally.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- platforms/macos.sh: call custom_reminders_section like linux_main —
  custom entries the engine does not run are now surfaced as manual
  reminders (mongodb-community appears on macOS for the first time)
  instead of silently dropped; gate the pipx [i/N] progress line on
  DRY_RUN; print a [dry-run] line for the sudo priming step; progress
  and FAIL lines for casks show the --adopt flag actually executed;
  keepalive refresh gets || true (inherited set -e) and stdout is
  redirected so piped runs see EOF at exit
- scripts/validate-packages.sh: handled_by_setup must be boolean if
  present (the engine tests == true, so a string "true" silently
  downgraded to a reminder); custom entries must resolve a string
  install_command for every platform they target
- macOS/lib-dmg-install.sh: trust the mount point hdiutil reports —
  it reuses an existing mount and ignores -mountpoint when the image
  is already attached (e.g. opened in Finder); cleanup re-registers
  with the mount actually used
- standardized.sh: free-tier Geekbench fallback greps the captured
  output for the browser URL before paying a second full CPU run, and
  appends instead of truncating the raw log
- omlx-bench.sh: with an explicit OMLX_MODEL a responding API counts
  as ready — lazy-loading servers list no models until first request

Validated: validate-packages passes the real packages.json and a
negative fixture catches all three new bad shapes; shellcheck +
bash -n clean; dryrun-smoke passes (macOS 87→88 actions: the new
[dry-run] sudo line); the macOS dry run shows the mongodb-community
reminder.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- benchmarks/lib.sh: bench_init owns the suite prologue (results dir,
  SYSINFO, HOSTNAME_SHORT/STAMP/OUTFILE, system banner) previously
  copy-pasted across all five suites; SUITE_VERSION replaces five
  "1.0.0" literals; openssl_sha256_kbs replaces the four copies of the
  openssl-speed run+parse in benchmark.sh/stress-test.sh
- platforms/macos.sh: mac_install_list is the single [i/N] install
  loop behind the brew/cask/pipx tiers (was three near-identical
  copies); as a side effect pipx failures now collect into the run
  summary instead of aborting setup under set -e
- codeburn menubar reminder is data-driven: new codeburn-menubar
  custom entry (priority none, handled_by_setup false) rendered by
  custom_reminders_section; the hardcoded name-check block in
  platform_main is gone
- lib-dmg-install.sh: install_app_from_dmg <AppName> <url> now owns
  the already-installed guard, curl/hdiutil dep checks, and the
  success line; both installers shrink to URL resolution (omlx keeps
  an early app_installed guard to skip the rate-limited GitHub API
  call on re-runs). info/die stay local — sourcing benchmarks/lib.sh
  would couple standalone installers to the suite's internals
- install-cinebench.sh: DMG_URL overridable via CINEBENCH_DMG_URL for
  when Maxon ships the next major version

Validated: validate-packages passes (106 entries), shellcheck +
bash -n clean, dryrun-smoke passes all four platforms (88 macOS
actions unchanged), dry run shows the codeburn-menubar reminder and
53 [i/N] lines through the shared loop; lib/core.sh untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ulises-c
ulises-c marked this pull request as ready for review July 1, 2026 22:58
@ulises-c
ulises-c merged commit dc5f569 into main Jul 1, 2026
5 checks passed
@ulises-c
ulises-c deleted the feat/packages-macos-benchmarks branch July 1, 2026 23:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant