Codex Desktop macOS GPU spike when focused
Summary
On macOS, the Codex Desktop app appears to trigger heavy sustained GPU/compositor activity whenever the Codex window is focused/frontmost. Switching focus to Chrome drops the GPU monitor to near idle immediately.
The effect reproduces with a small A/B script that focuses Chrome, samples powermetrics, then focuses Codex and samples again.
Environment
- App: Codex Desktop
- Bundle ID:
com.openai.codex - Codex version:
26.623.61825(CFBundleVersion4548) - Chromium base:
149.0.7827.197 - Machine:
Mac15,10, Apple Silicon /arm64 - macOS:
27.0build26A5368g - Kernel:
Darwin 27.0.0
Quick reproduction
- Open Chrome and Codex Desktop.
- Run a focus A/B capture:
sudo powermetrics \
--sample-rate 1000 \
--sample-count 8 \
--samplers tasks,gpu_power,cpu_power,thermal \
--show-process-gpu \
--show-process-energy \
--output-file <output.txt>
- Capture once with Chrome focused and once with Codex focused. In my local script, focus switching is done with
osascriptusing bundle IDscom.google.Chromeandcom.openai.codex.
Portable repro and logging script
The following script should run on any macOS machine with Codex installed in /Applications/Codex.app. It creates a timestamped folder containing:
metadata.txt: macOS, hardware, Codex version, current Codex process flags, thermal status, swap status.Chrome-powermetrics.txt: raw baseline capture.Codex-powermetrics.txt: raw target capture.summary.txt: compact GPU active/power comparison to paste into an issue.
Usage:
chmod +x repro-codex-gpu-focus.sh
./repro-codex-gpu-focus.sh
If Chrome is not the desired baseline app, override the bundle ID:
BASELINE_APP_ID=com.apple.Safari BASELINE_LABEL=Safari ./repro-codex-gpu-focus.sh
repro-codex-gpu-focus.sh
#!/usr/bin/env bash
set -euo pipefail
SAMPLE_COUNT="${SAMPLE_COUNT:-8}"
SAMPLE_RATE_MS="${SAMPLE_RATE_MS:-1000}"
SETTLE_SECONDS="${SETTLE_SECONDS:-3}"
BASELINE_APP_ID="${BASELINE_APP_ID:-com.google.Chrome}"
TARGET_APP_ID="${TARGET_APP_ID:-com.openai.codex}"
BASELINE_LABEL="${BASELINE_LABEL:-Chrome}"
TARGET_LABEL="${TARGET_LABEL:-Codex}"
OUT_DIR="${1:-./codex-gpu-repro-$(date +%Y%m%d-%H%M%S)}"
mkdir -p "$OUT_DIR"
{
echo "# System"
sw_vers 2>/dev/null || true
echo "hw.model: $(sysctl -n hw.model 2>/dev/null || true)"
echo "kernel: $(uname -a 2>/dev/null || true)"
echo
echo "# Codex app"
defaults read /Applications/Codex.app/Contents/Info CFBundleShortVersionString 2>/dev/null | sed 's/^/CFBundleShortVersionString: /' || true
defaults read /Applications/Codex.app/Contents/Info CFBundleVersion 2>/dev/null | sed 's/^/CFBundleVersion: /' || true
defaults read /Applications/Codex.app/Contents/Info ChromiumBaseVersion 2>/dev/null | sed 's/^/ChromiumBaseVersion: /' || true
echo
echo "# Codex processes"
ps -axo pid,ppid,stat,etime,%cpu,%mem,rss,command | grep -E '/Applications/Codex.app|Codex \\(|codex app-server' | grep -v grep || true
echo
echo "# Thermal and swap"
pmset -g therm 2>/dev/null || true
sysctl -n vm.swapusage 2>/dev/null | sed 's/^/swap: /' || true
} >"$OUT_DIR/metadata.txt"
capture() {
label="$1"
app_id="$2"
echo "Activating $label..."
osascript -e "tell application id \"$app_id\" to activate"
sleep "$SETTLE_SECONDS"
sudo powermetrics \
--sample-rate "$SAMPLE_RATE_MS" \
--sample-count "$SAMPLE_COUNT" \
--samplers tasks,gpu_power,cpu_power,thermal \
--show-process-gpu \
--show-process-energy \
--output-file "$OUT_DIR/${label}-powermetrics.txt" \
2>"$OUT_DIR/${label}-powermetrics.stderr.log"
}
summarize() {
label="$1"
file="$2"
perl -MList::Util=sum,min,max -e '
my ($label, $file) = @ARGV;
open my $fh, "<", $file or die "Unable to read $file: $!\n";
my (@gpu_power, @gpu_active);
while (<$fh>) {
push @gpu_power, $1 if /GPU Power:\s*(\d+)\s*mW/;
push @gpu_active, $1 if /GPU HW active residency:\s*([0-9.]+)%/;
}
printf "%-10s active avg=%6.2f%% max=%6.2f%% | power avg=%5.0f mW max=%5d mW | %s\n",
$label, sum(@gpu_active) / @gpu_active, max(@gpu_active),
sum(@gpu_power) / @gpu_power, max(@gpu_power), $file;
' "$label" "$file"
}
echo "Output folder: $OUT_DIR"
sudo -v
capture "$BASELINE_LABEL" "$BASELINE_APP_ID"
capture "$TARGET_LABEL" "$TARGET_APP_ID"
{
echo "# GPU focus comparison"
summarize "$BASELINE_LABEL" "$OUT_DIR/${BASELINE_LABEL}-powermetrics.txt"
summarize "$TARGET_LABEL" "$OUT_DIR/${TARGET_LABEL}-powermetrics.txt"
echo
echo "# Attach"
echo "$OUT_DIR/summary.txt"
echo "$OUT_DIR/metadata.txt"
echo "$OUT_DIR/${BASELINE_LABEL}-powermetrics.txt"
echo "$OUT_DIR/${TARGET_LABEL}-powermetrics.txt"
} | tee "$OUT_DIR/summary.txt"
Results
| Launch mode | Focused app | GPU active avg | GPU active max | GPU power avg | GPU power max |
|---|---|---|---|---|---|
| Normal Codex launch | Chrome | 1.94% |
2.92% |
19 mW |
26 mW |
| Normal Codex launch | Codex | 70.16% |
76.86% |
2324 mW |
3214 mW |
| Reduced-GPU flags | Chrome | 1.70% |
2.11% |
15 mW |
19 mW |
| Reduced-GPU flags | Codex | 70.84% |
78.59% |
2644 mW |
3404 mW |
Reduced-GPU test flags:
open -a "Codex" --args \
--disable-zero-copy \
--disable-gpu-memory-buffer-compositor-resources \
--disable-accelerated-2d-canvas \
--disable-accelerated-video-decode \
--disable-features=CanvasOopRasterization
The reduced flags were visible in the Codex process command line, but did not reduce the GPU load. A harder launch using --disable-gpu --disable-gpu-compositing caused Codex to start without a visible window and required force quit, so that path was not usable.
Additional observations
pmset -g thermreported no thermal or performance warnings.sysctl -n vm.swapusagereported0.00Mswap used.powermetricsoften attributes the sustained work toWindowServerrather than directly to Codex per-process GPU columns, but the focus A/B isolates the trigger to Codex being frontmost.- Other background CPU noise was present during some captures (
fileproviderd,bird,cloudd), but it did not explain the GPU delta: Chrome focus stayed around 2% GPU active while Codex focus stayed around 70%.
Expected
An idle/focused Codex Desktop window should not sustain roughly 70% GPU active residency and 2.3-2.6 W GPU power when another Chromium/Electron-style app focus state is near idle.
Request
Please investigate whether the focused Codex Desktop window has a rendering/compositor loop or macOS WindowServer interaction that keeps the GPU active. I can provide the raw powermetrics captures if useful.