INC-2026-04-04: Investigation
Investigation
Phase 1: Thermal Baseline
paste <(cat /sys/class/thermal/thermal_zone*/type) \
<(awk '{printf "%.1f°C\n", $1/1000}' /sys/class/thermal/thermal_zone*/temp)
| Sensor | Temperature |
|---|---|
x86_pkg_temp (CPU) |
86.0°C |
acpitz |
81.0°C |
SEN1/SEN2 (VRM/SSD) |
53-54°C |
NVIDIA RTX 5090 |
54°C (idle) |
iwlwifi |
60°C |
Phase 2: Process Analysis
top -b -n1 | awk 'NR>=7 && NR<=12'
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2140 evanusm+ 20 0 2391024 93284 77544 R 96.1 0.1 11,21 waybar
2084 evanusm+ 20 0 1570524 203848 113288 S 4.8 0.3 35:45.76 Hyprland
waybar at 96.1% CPU — single core pinned. 11 minutes 21 seconds of accumulated CPU time.
Phase 3: GPU Verification
nvidia-smi
| 0 NVIDIA GeForce RTX 5090 Off | 00000000:01:00.0 Off | N/A |
| N/A 54C P8 7W / 95W | 17MiB / 24463MiB | 0% Default |
Processes:
| 0 N/A N/A 2084 G Hyprland 6MiB |
Only Hyprland on GPU at 6 MiB. Firefox and kitty NOT on dGPU (unlike INC-2026-03-27).
Phase 4: Isolation Testing
Systematic elimination to identify root cause:
| Test | Config | CPU Result |
|---|---|---|
Minimal (clock only, minimal CSS) |
1 module, no styling |
0.0% |
Full modules, minimal CSS |
All modules, |
0.0% |
Full modules, full CSS (no animations) |
All modules, animations commented |
53% |
Full modules, full CSS (no transitions) |
All modules, transitions + animations off |
58% |
Full modules, full CSS (no box-shadow) |
All modules, box-shadow + animations + transitions off |
CSS parse error (broken comments) |
Full modules, properly cleaned CSS |
Removed box-shadow blocks, fixed syntax, disabled last animation |
0.0% |
Conclusion: Full modules + minimal CSS = 0%. The CSS itself was the sole cause.
Phase 5: CSS Forensics
The style.css (605 lines, Catppuccin Mocha / Glass Island theme) contained:
| Property | Count |
|---|---|
|
~80+ |
|
8 (including multi-line) |
|
~20 |
|
4 |
Infinite |
7 (pulse, glow-pulse, text-flicker, border-glow-cycle, subtle-breathe) |
|
3 |
|
2 |
Findings
-
Primary: Multi-line
box-shadowwithalpha()compositing forced GTK3 into software rendering path for every widget repaint -
Contributing: Seven infinite CSS animations triggered constant repaints every frame, each requiring expensive shadow recalculation
-
Trigger: The degradation was progressive over 1 day 20h uptime — GTK3’s rendering pipeline accumulated overhead until it entered a CPU spin
-
Correlation: Plugging in AC power likely triggered a battery state class change (
.charging), causing a style recalculation cascade on all widgets simultaneously
Root Cause
Technical explanation: GTK3’s CSS engine performs box-shadow rendering in software (CPU), not GPU-accelerated. The waybar theme used 8 box-shadow declarations combined with alpha() transparency compositing and 7 infinite CSS animations. Each animation frame triggered a repaint cycle that required recalculating shadows and alpha blending for every affected widget. Over ~44 hours of uptime, GTK3’s rendering pipeline degraded until the repaint cost exceeded one frame budget, causing a sustained CPU spin at 50-96%.
Why it happened:
-
Immediate cause: GTK3 CSS repaint loop driven by
box-shadow+alpha()compositing -
Contributing factors: 7 infinite CSS animations forcing constant repaints, ~44h uptime without waybar restart
-
Trigger: AC power plug-in caused battery class change (
.charging), cascading style recalculation -
Systemic issues: No awareness that GTK3 CSS
box-shadowis CPU-rendered, no performance testing of the theme