Skip to content

Screensaver saturates 5+ CPU cores and thermally throttles on HiDPI displays (foot is software-rendered, hardcoded --frame-rate 120) #9193

Description

@markvogel

Summary

On a HiDPI display, the screensaver saturates several CPU cores and drives the
machine into sustained thermal throttling. The cost scales with device
pixels
, so it gets bad on a single 4K/5K panel and worse with more monitors.

Root cause is a combination of three things, all in the default configuration:

  1. omarchy-launch-screensaver opens one fullscreen terminal per monitor.
  2. omarchy-screensaver runs ttfx with a hardcoded --frame-rate 120.
  3. Omarchy's only shipped/listed terminal is foot, which is a software
    renderer — it rasterizes with libpixman into a wl_shm buffer and links no
    libGL/libEGL/libvulkan.

Every screensaver frame is therefore rasterized on the CPU, full-screen, at
120fps, at native panel resolution.

Measurements

Captured live while the screensaver was up (Framework 13, Core Ultra 7 165H,
Intel Arc iGPU, 3 monitors):

Window Monitor Logical Scale Device px CPU
foot eDP-1 (laptop) 1440x960 2 2880x1920 125%
foot DP-4 (ASUS 1440p) 2560x1440 1 2560x1440 103%
foot DP-3 (ViewSonic 5K) 2560x1440 2 5120x2880 303%

Total ≈ 531% CPU (5.3 cores). Meanwhile Hyprland stayed at 9-11% and all
ttfx processes combined stayed under 10% — the compositor and the effect
generator are both cheap. The cost is entirely foot's CPU rasterization.

Thermals over roughly three minutes of screensaver:

  • Package temp: 60 C -> 97 C (crit 110)
  • Fan: 2421 -> 5682 RPM
  • package_throttle_count: 638 -> 1097

The two 1440p windows isolate the variable

DP-3 and DP-4 both got a 2560x1440 logical window — identical character
grid, identical font size, identical effect. The only difference is scale:
DP-3 renders 4x the device pixels and costs ~3x the CPU (303% vs 103%).

That rules out monitor count, grid size and effect complexity as the driver.
It is pixel-bound software rasterization. A single 5K display with no other
monitors attached would still cost ~300%.

Isolating ttfx

Running ttfx alone into an off-screen pty at the same grid (232x60) and
--frame-rate 120 costs 1.2% CPU. ttfx is not the problem; it is cheap
regardless of framerate. All of the cost is on the terminal-rendering side.

Why this is the default path

  • default/xdg-terminal-exec/hyprland-xdg-terminals.list lists only foot.desktop
  • install/omarchy-base.packages installs only foot
  • omarchy-screensaver also supports Alacritty / Ghostty / Kitty, which are all
    OpenGL-accelerated and would be dramatically cheaper — but a stock install
    never takes that path.

Additional notes

  • --frame-rate 120 is requested against 60Hz panels, so a portion of the
    generated and parsed output can never be displayed.
  • The idle cycle re-arms, so an unattended machine repeats the ~150s burn every
    cycle rather than doing it once.

Suggestions

Offered as options, not a prescription:

  • Cap the framerate to the monitor's refresh rate, or lower the default well
    below 120 (30-60 looks identical for these effects).
  • Scale the framerate down as device-pixel count rises.
  • Expose the framerate as a setting in shell.json alongside
    idle.screensaver / idle.lock, so it can be tuned without editing a
    package-owned file in /usr/share/omarchy/.
  • Consider skipping or simplifying the screensaver above some pixel threshold.

Workaround

omarchy toggle screensaver, or set idle.lock close to idle.screensaver in
~/.config/omarchy/shell.json so hyprlock takes over quickly.

System details

Omarchy   4.0.1-1
Hyprland  0.56.2-1
foot      1.27.0-2
ttfx      0.3.2-1
mesa      1:26.2.1-1
kernel    7.1.9-arch1-2
CPU       Intel Core Ultra 7 165H (22 threads)
GPU       Intel Arc / Meteor Lake-P [8086:7d55], i915
Laptop    Framework
Monitors  eDP-1 2880x1920@120 scale2 / DP-3 5120x2880@60 scale2 / DP-4 2560x1440@60 scale1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions