Native Apple Silicon CPU, GPU, and unified-memory stress testing for macOS.
Current version: 1.1
MacStress is a sandboxed SwiftUI app for applying sustained, configurable load to Apple Silicon hardware while observing CPU utilization, GPU utilization, throughput, elapsed time, and system thermal pressure.
Warning
MacStress is intentionally aggressive. Tests can rapidly increase temperature, fan speed, system power draw, and battery drain. Sustained runs may cause macOS to reduce performance in response to thermal pressure. Use the app on a stable, ventilated surface and supervise high-power tests.
- Native SwiftUI dashboard with one start/stop control.
- Five system presets and configurable duration limits.
- Per-performance-level CPU worker controls discovered from macOS topology data.
- Three CPU workload profiles and five GPU workload profiles.
- Stable rolling 60-second CPU/GPU utilization chart with independent, bounded series.
- Live compute throughput in TFLOPS or effective kernel traffic in GB/s, depending on the GPU profile.
- Post-test report with duration, average and peak utilization, peak throughput, and serious thermal-pressure observations.
- Coordinated shutdown that waits for CPU workers and submitted Metal command buffers before declaring a run complete.
- App version sourced from the built bundle rather than duplicated in the UI.
| Preset | CPU workload | GPU workload | Intended use |
|---|---|---|---|
| Full System | ALU on all enabled CPU tiers | Extreme | Broad CPU and GPU compute, matrix, cache, and memory activity |
| CPU Only | ALU on all enabled CPU tiers | Off | Sustained CPU arithmetic load |
| GPU Only | Off | Extreme | Sustained GPU compute and mixed-subsystem load |
| Memory Bus | Bandwidth | Bandwidth | Concurrent CPU/GPU unified-memory traffic |
| Custom | Selected profile and worker counts | Selected profile | Manual workload composition and diagnostics |
Available duration limits are 1, 5, 10, 15, or 30 minutes, plus an explicit No Limit option. The default is 5 minutes.
| Profile | Behavior |
|---|---|
| ALU | One native worker per configured slot running 12 independent FP32x4 NEON FMA chains plus four integer multiply-accumulate chains |
| Mixed | ALU workers plus randomized, partitioned memory traffic |
| Bandwidth | 128-bit NEON streaming reads/writes over non-overlapping per-worker buffer slices; no extra ALU workers |
MacStress reads hw.nperflevels and hw.perflevelN.* to identify the CPU tiers exposed by the current Mac. Worker QoS is selected from those tier names. QoS is a scheduler hint: macOS does not provide a public API for hard-pinning application threads to specific performance or efficiency cores.
CPU memory profiles allocate a zero-backed buffer sized from physical memory, bounded between 128 MiB and 1 GiB. Each worker receives its own power-of-two, cache-line-aligned slice to avoid data races and unintended worker contention.
| Profile | Behavior | Reported metric |
|---|---|---|
| Extreme | FP32/FP16 vector ALUs, SIMD-group matrix operations, threadgroup memory, and unified-memory activity | TFLOPS |
| Matrix | Sustained half-precision 8×8 SIMD-group matrix multiply-accumulate operations | TFLOPS |
| Vector ALU | Sustained independent FP32 and FP16 vector FMA chains | TFLOPS |
| Bandwidth | Coalesced 128-bit streaming reads and writes across unified memory | Effective GB/s |
| Mixed | Vector arithmetic with moderate coalesced unified-memory traffic | TFLOPS |
Every GPU path writes observable results to a Metal buffer, preventing the compiler from eliminating the intended work. Dispatch sizes are selected per profile from the device pipeline width and available work-buffer capacity. The engine keeps up to three command buffers in flight and only counts successfully completed buffers toward throughput.
GPUStressKernel.metal is bundled as source and compiled at runtime. This keeps a single shader source of truth and means the project does not require Xcode's optional Metal Toolchain package merely to build the app.
- CPU utilization is system-wide utilization sampled from Mach processor tick deltas. The baseline is primed when a run starts.
- GPU utilization is sampled asynchronously from the
IOAcceleratorregistry so IOKit polling does not block the UI. This is a best-effort macOS implementation detail and may vary between OS or hardware versions. - TFLOPS is derived from the explicit operation count of successfully completed kernel dispatches divided by elapsed time. It is not a hardware performance-counter reading.
- GB/s is effective kernel read/write traffic derived from completed dispatches. It is not a physical DRAM-controller counter.
- Thermal state comes from
ProcessInfo.thermalState. It reports system thermal pressure but does not directly prove a particular clock frequency or throttling event. - Profile names describe the hardware mix, not a guaranteed wall-power ordering. Bandwidth can draw more total-system power than Extreme because it drives unified DRAM continuously; Extreme is the broader GPU compute/matrix/shared-memory workload.
- Configuration controls are locked while a test is running or stopping.
- A second run cannot begin until all workers and in-flight GPU work from the previous run have stopped.
- CPU workers use a C11 atomic stop token shared safely between Swift and C.
- GPU telemetry samples are generation-tagged so late asynchronous results cannot leak into a later run.
- The duration limiter automatically requests a coordinated stop when its deadline is reached.
- Startup failures are surfaced in the UI; a partially available CPU/GPU configuration can continue with a warning when at least one requested engine starts.
Duration limits reduce unattended risk, but they are not a substitute for supervision or adequate cooling.
- Apple Silicon Mac (M1 or later).
- macOS 14 Sonoma or later.
- Xcode 15 or later when building from source.
The latest GitHub release provides:
MacStress-v1.1.dmg— mount the disk image and copy MacStress to Applications.MacStress-v1.1.app.zip— the same application bundle as a ZIP archive.SHA256SUMS.txt— SHA-256 checksums for both downloads.
Release applications are ad-hoc signed but not Apple-notarized. Depending on local Gatekeeper policy, macOS may require explicit approval before the first launch.
Open MacStress.xcodeproj in Xcode and run the shared MacStress scheme, or build from Terminal:
xcodebuild -project MacStress.xcodeproj \
-scheme MacStress \
-configuration Release \
-destination 'platform=macOS,arch=arm64' \
-derivedDataPath /tmp/MacStressDerivedData \
buildThe app will be created at:
/tmp/MacStressDerivedData/Build/Products/Release/MacStress.app
The standard scheme tests run-state transitions, chart series/windowing, the C11 atomic stop token, and GPU metric selection. The heat-producing GPU benchmark is skipped here.
xcodebuild -project MacStress.xcodeproj \
-scheme MacStress \
-destination 'platform=macOS,arch=arm64' \
-derivedDataPath /tmp/MacStressTests \
testThis scheme runs every GPU profile, verifies completed work and the appropriate throughput metric, and requires sustained utilization above 50%. It deliberately creates substantial heat and power draw.
xcodebuild -project MacStress.xcodeproj \
-scheme MacStress-GPU-Benchmarks \
-destination 'platform=macOS,arch=arm64' \
-derivedDataPath /tmp/MacStressGPUBenchmarks \
-only-testing:MacStressTests/GPUStressEngineValidationTests \
testscripts/validate_stresskernels_codegen.shThe script compiles the C hot loop to assembly and checks for at least 12 fmla.4s instructions and zero redundant mov.16b operations in the validated loop.
Pushing a version tag such as v1.1 runs .github/workflows/release.yml on an Apple Silicon GitHub Actions runner. The workflow verifies that the tag matches MARKETING_VERSION, runs the unit and CPU code-generation checks, builds an ARM64 Release app, ad-hoc signs it, creates the ZIP and DMG downloads, writes their checksums, and publishes or updates the matching GitHub release.
| Path | Purpose |
|---|---|
MacStress/ContentView.swift |
Dashboard, charts, controls, and summary presentation |
MacStress/StressCoordinator.swift |
Presets, timing, telemetry history, reports, and coordinated lifecycle |
MacStress/StressEngine.swift |
CPU topology, worker configuration, and memory-buffer management |
MacStress/StressKernels.c |
Native NEON, memory-streaming, and atomic stop implementations |
MacStress/GPUStressEngine.swift |
Metal setup, dispatch scheduling, telemetry, and metric accounting |
MacStress/GPUStressKernel.metal |
Runtime-compiled GPU workload implementations |
MacStressTests/ |
Unit and opt-in GPU regression coverage |
scripts/validate_stresskernels_codegen.sh |
CPU hot-loop assembly regression check |