Stop Linux Gaming Stutter: Automatic CPU Scheduler Switching with sched_ext (2026)


estimated read time: 13 minutes

TL;DR

Install scx-scheds, drop a config into Gamemode, and add gamemoderun to your Steam launch options. Every game automatically switches to a low-latency CPU scheduler on launch and switches back when you’re done. Takes about 20 minutes. Works on Intel and AMD.

I’ve been running Linux as my daily gaming OS for a while now and the one thing that kept bugging me was stutter — not from GPU drivers or Proton, but from the CPU scheduler treating a game with the same priority as any other process. Kernel 6.12 finally gives us a clean fix for this, and it’s surprisingly straightforward to set up.

Quick Setup

Prerequisites

Check your kernel:

uname -r
# Should be 6.12.0 or higher

If you need to upgrade:

sudo pacman -S linux-zen linux-zen-headers
# Then reboot

Step 1: Install scx Schedulers

scx-scheds is in the official Arch repos — no AUR needed:

sudo pacman -S scx-scheds

Verify:

scxctl list
# Should show: lavd, rusty, bpfland, central, etc.

Step 2: Polkit — Passwordless Switching

Gamemode needs to call scxctl without a password prompt. Create a polkit rule for wheel group users:

sudo nano /etc/polkit-1/rules.d/99-scx-loader.rules

Paste:

polkit.addRule(function (action, subject) {
  if (action.id.indexOf("org.scx.") === 0 && subject.isInGroup("wheel")) {
    return polkit.Result.YES;
  }
});

Reload polkit:

sudo systemctl restart polkit

Test it works without a password prompt:

scxctl switch -s lavd
scxctl status
# Should show: Current scheduler: lavd

scxctl switch -s rusty

Step 3: Install & Configure Gamemode

sudo pacman -S gamemode lib32-gamemode
sudo systemctl enable --now gamemoded

First, check your CPU so you know which config to use:

lscpu | grep "Model name"

Create /etc/gamemode.ini:

sudo nano /etc/gamemode.ini

Intel, or AMD without X3D (most users) — just the scheduler switch, nothing else needed:

[custom]
; Switch to low-latency scheduler when a game launches
start=scxctl switch -s lavd
; Switch back to throughput scheduler when the game closes
stop=scxctl switch -s rusty

AMD Ryzen 7800X3D — single V-Cache CCD, core pinning is optional but adds a small benefit:

[cpu]
; 7800X3D has one CCD, so all cores have V-Cache — pinning reduces migration overhead
pin_cores=0-7

[custom]
start=scxctl switch -s lavd
stop=scxctl switch -s rusty

AMD Ryzen 7950X3D or 7900X3D — two CCDs but only CCD0 has V-Cache, so pinning is important here. Without it the scheduler can silently put your game on the slower die:

[cpu]
; Pins games to the V-Cache die (CCD0). Cores 0-7 physical, 16-23 their SMT siblings
pin_cores=0-7,16-23

[custom]
start=scxctl switch -s lavd
stop=scxctl switch -s rusty

Not sure which applies to you? See the Core Pinning section for a full explanation of the architecture difference.

Restart the Gamemode daemon:

sudo systemctl restart gamemoded

Step 4: Enable for Your Games

Steam: Right-click a game → Properties → General → Launch Options:

gamemoderun %command%

Lutris: System Options → Enable Gamemode (checkbox).

Heroic Games Launcher: Add gamemoderun to the game’s launch arguments.

That’s it. Every game launch now automatically switches to scx_lavd. Every close switches back to scx_rusty.

Verifying It Works

Launch a game, then in a terminal:

scxctl status
# Should show: Current scheduler: lavd

Watch Gamemode logs in real time:

journalctl -u gamemoded -f

Close the game:

scxctl status
# Should show: Current scheduler: rusty

Not on Arch Linux?

Other distros: The scx schedulers and Gamemode config are identical on Fedora, Ubuntu, and Pop!_OS — only the package manager differs. On Fedora: sudo dnf install scx-scheds gamemode. On Ubuntu 24.04+: sudo apt install scx-scheds gamemode. The polkit rules and gamemode.ini config are copy-paste identical.

Intel CPUs: Everything in this guide works the same way on Intel. The only section that doesn’t apply is the Ryzen X3D core pinning — skip pin_cores in your gamemode.ini and follow the rest as-is.


How It Works

The Problem: CFS Doesn’t Optimize for Gaming

Linux gaming in 2026 is excellent — Proton, solid GPU drivers, Steam Deck — but most distributions still use the Completely Fair Scheduler (CFS). CFS is designed for server workloads: maximize throughput, treat everything fairly.

That’s the problem. When you’re gaming and a background task spins up (Discord, browser, compiler), CFS gives both equal CPU time. Your game stutters because the scheduler doesn’t know it’s latency-sensitive.

sched_ext changes this. Merged in Linux 6.12, it lets you hot-swap CPU schedulers at runtime — no reboot, no kernel rebuild, just load a different scheduler based on your workload.

Why Two Schedulers?

Like many home Linux desktop users, my main machine is a multi-purpose workstation — switching between admin tasks like writing documentation, programming, and CPU/GPU-intensive creative workflows. In any case, I want the CPU to optimise its performance for whatever is in front of me at the time.

PC gaming adds a unique angle to this. Most games are optimised for 8 threads of compute rather than raw parallelism, but players are acutely sensitive to any frame delay that presents itself as a stutter, elastic-banding, or input lag. The reason I’ve chosen two schedulers is exactly that: I want my PC to automatically shift gear when I start a game, moving from a throughput-focused desktop mode to one that minimises latency and delivers smooth gameplay.

scx_lavd (Latency-criticality Aware Virtual Deadline) was developed by Igalia for the Steam Deck. It minimizes latency spikes, improves 1% low FPS, and keeps games responsive even with background tasks running. Meta uses it in production because it handles mixed workloads brilliantly.

scx_rusty is a general-purpose global scheduler optimized for throughput. Perfect for desktop use: browser tabs, background compilation, music streaming. In my testing, scx_rusty gave 5-7x throughput improvement over CFS for parallel builds.

scx_lavd vs scx_rusty: Quick Comparison

Featurescx_lavdscx_rustyCFS (default)
Optimized forGaming, low latencyThroughput, desktopGeneral fairness
1% Low FPS⭐⭐⭐⭐⭐ Best⭐⭐ Poor⭐⭐⭐ Good
Compile Speed⭐⭐⭐ Good⭐⭐⭐⭐⭐ 5-7x faster⭐⭐⭐ Baseline
Frame Time Variance2.9ms (smooth)4.8ms (stuttery)4.2ms (okay)
Best Use CaseFPS/action gamesBackground tasksServer workloads

Use scx_lavd when gaming, scx_rusty for everything else.

Understanding Gamemode

Gamemode is a daemon from Feral Interactive (the studio behind Linux ports of games like Total War and XCOM) that automatically applies a suite of performance optimisations the moment a game launches — and undoes them cleanly when the game closes.

Think of it as a “gaming profile” that runs in the background. When you start a game, Gamemode:

The key word is automatic. You don’t open a terminal, you don’t run a script manually — you just launch your game the usual way via Steam or Lutris, and Gamemode handles everything in the background.

If you’ve heard of Windows tools like Process Lasso or Razer Cortex, Gamemode is the Linux equivalent — except it’s open source, lightweight (~1MB), and integrates cleanly with the desktop.

How the hook works

Gamemode exposes two custom command slots in its config:

We use these to call scxctl switch, so the scheduler changes happen alongside all the other optimisations with zero extra effort from you.

Testing Schedulers Manually

Before relying on Gamemode, it’s worth verifying the schedulers work as expected.

Baseline: Default CFS

stress-ng --cpu $(nproc) --timeout 30s --metrics-brief

Note the “bogo ops/sec” — this is your baseline throughput.

scx_rusty: General Compute

scxctl switch -s rusty
stress-ng --cpu $(nproc) --timeout 30s --metrics-brief

On my machine (Ryzen 9 7950X3D, 16C/32T):

Your numbers will vary by CPU, but the relative gap between schedulers should be consistent.

scx_lavd: Gaming Mode

scxctl switch -s lavd

Run the stress test — you’ll see lower throughput than scx_rusty. That’s intentional: scx_lavd trades raw throughput for latency.

Switch back when done:

scxctl switch -s rusty

Advanced: Ryzen 7950X3D Core Pinning Explained

The pin_cores=0-7,16-23 line in the Gamemode config is critical for 7950X3D and 7900X3D performance.

The Problem: Dual-CCD Architecture

Ryzen 7950X3D has two CCDs (chiplets):

Only CCD0 has the 3D V-Cache. If your game runs on CCD1, you lose 20-30% FPS.

On Windows, the Xbox Game Bar driver automatically pins games to CCD0. Linux doesn’t have this. Without manual pinning, the scheduler randomly assigns cores, and your game will:

  1. Run on the wrong CCD (slower)
  2. Migrate between CCDs mid-game (stuttering)
  3. Fight with background tasks for V-Cache cores

Core Topology on 7950X3D

Cores 0-7:   Physical cores (CCD0, 3D V-Cache) ← Pin games here
Cores 8-15:  Physical cores (CCD1, regular cache)
Cores 16-23: SMT siblings of 0-7 (CCD0)
Cores 24-31: SMT siblings of 8-15 (CCD1)

By pinning to 0-7,16-23 we lock the game to CCD0, use all 8 physical cores and their SMT threads, and let background tasks run freely on CCD1.

Verifying Your CCD Layout

lscpu -e
# Look for cores 0-7 and their L3 cache size

Or install hwloc for a visual diagram:

sudo pacman -S hwloc
lstopo --no-io

Should You Pin?

CPUAction
7950X3DMandatory — 2 CCDs, only CCD0 has V-Cache
7900X3DMandatory — same architecture
7800X3DOptional — single CCD, all cores have V-Cache
Non-X3DNot needed — no cache difference between chiplets

Advanced: Spring Boot Benchmark — Why scx_rusty Wins for Desktop

To confirm which scheduler to use when not gaming, I ran scx schedulers under realistic CPU load using a Spring Boot banking application — the same kind of pressure you’d see from a background compiler, Docker build, or local dev server.

Test Setup

Results

SchedulerSuccess RateMean Responsep95 ResponseBest For
scx_rusty95.2%1,154ms5,048msCPU-intensive throughput
scx_lavd100%19,895ms39,669msInteractive/latency-sensitive
CFS (default)77.7%1,669ms9,392msGeneral purpose baseline
scx_layered98.7%38,458ms57,502msMulti-tenant fairness
scx_bpfland31.8%22,696ms53,974ms❌ Poor fit for this workload

scx_rusty’s work-stealing, load-balancing design keeps all cores busy for CPU-bound tasks. scx_lavd trades that raw throughput for latency guarantees — the right call for gaming, the wrong call for batch processing.

Full benchmark details: github.com/dfoulkes/scx_test_harness

Monitoring Scheduler Performance

# Check current scheduler
scxctl status

# List all available schedulers
scxctl list

# Deeper kernel-level stats (requires debugfs)
sudo cat /sys/kernel/debug/sched/ext/stats

The stats file shows latency percentiles (p50, p90, p99), runqueue depth, and context switches — useful if you want to confirm scx_lavd is actually reducing tail latency.

Troubleshooting

scxctl says “sched_ext not supported”

uname -r
# Must be 6.12.0 or higher

zgrep CONFIG_SCHED_CLASS_EXT /proc/config.gz
# Should show: CONFIG_SCHED_CLASS_EXT=y

If the config flag is missing, switch to linux-zen:

sudo pacman -S linux-zen linux-zen-headers

Gamemode doesn’t switch schedulers

# Check the daemon is running
systemctl status gamemoded

# Test scxctl manually (should work without a password prompt)
scxctl switch -s lavd
scxctl status

# If you get a password prompt, verify the polkit rule
cat /etc/polkit-1/rules.d/99-scx-loader.rules
sudo systemctl restart polkit

Scheduler crashes or game stutters

dmesg | grep scx

Common cause: CPU governor stuck on powersave. Fix immediately:

echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

Make it permanent via Gamemode:

[cpu]
governor=performance

Why This Matters

Most Linux gaming guides obsess over GPU drivers, Proton, and Wine. Almost no one talks about the CPU scheduler — even though it’s the first thing your game interacts with.

sched_ext changes the game. We can now optimize the scheduler for the workload:

Linux gaming in 2026 isn’t just “good enough” — it’s competitive. scx_lavd can deliver smoother frame pacing than Windows defaults because the scheduler is optimised specifically for latency-sensitive interactive workloads, regardless of what CPU you’re running.

This is why Steam Deck works. This is why Valve invested in sched_ext. The future is here.

FAQ

Does scx_lavd work on Intel CPUs? Yes. scx_lavd is scheduler logic, not hardware-specific. Intel users won’t benefit from the CCD core pinning, but the latency improvements and automatic Gamemode switching work identically.

Do I need to reboot to switch schedulers? No. That’s the entire point of sched_ext — schedulers are hot-swappable at runtime via scxctl switch. No reboot, no kernel module reload.

Will this break anything? scx schedulers run in BPF userspace and fall back gracefully to CFS if they crash. The worst case is your game reverts to CFS mid-session. In practice, scx_lavd and scx_rusty are stable on 6.12+ kernels.

What’s the difference between scx_lavd and scx_bpfland? Both target low latency but use different scheduling policies. My benchmarks show scx_bpfland performing poorly under mixed workloads. Stick with scx_lavd for gaming.

Does this work with Lutris and Heroic Games Launcher? Yes. Enable Gamemode in Lutris via System Options → Enable Gamemode. For Heroic, add gamemoderun to the game’s launch arguments. The scheduler switching happens the same way.

Is this the same as what Steam Deck uses? Yes — Valve ships scx_lavd on Steam Deck OS for exactly this reason. This guide replicates that setup on desktop Arch Linux.

Do I need a Ryzen X3D CPU to benefit? No. Any CPU on kernel 6.12+ benefits from scx_lavd’s latency improvements. The core pinning section is X3D-specific, but the rest of the guide applies universally.

Further Reading

Conclusion

This setup takes 20 minutes to configure and delivers measurable improvements. scx_lavd reduces stutter and improves 1% lows for gaming; scx_rusty gives you back full throughput the moment you close the game. Gamemode automates the switch so you never think about it again.

The magic isn’t in the hardware. It’s in the scheduler understanding that your game is latency-sensitive and your background Discord isn’t.


Questions? Find me on GitHub.