Intro
Before we dive into each parameter, a quick reminder:
The Linux scheduler’s job is to share CPU time among all running tasks. It tries to balance responsiveness (how quickly apps react) and throughput (how much total work gets done).
When tuning these parameters, we’re effectively telling the kernel how aggressive or relaxed we want it to be about switching tasks and handling CPU load distribution.
For gaming, real-time workloads, or benchmarks, we often prioritize responsiveness and latency over raw fairness — meaning faster reaction times at the cost of slightly more CPU context-switching overhead.
1. kernel.sched_min_granularity_ns = 1000000
Default: 1000000 (1 millisecond)
Meaning: Minimum time slice (in nanoseconds) a task runs before the scheduler considers switching to another one.
- Think of it as the minimum attention span the CPU gives to a task.
- Lower values → the CPU switches between tasks more frequently → better responsiveness, but higher context-switching overhead.
- Higher values → tasks run longer before being interrupted → better throughput, but slower reaction to input or real-time tasks.
Tuning tip:
Keep it low (like 1000000 or 750000) for gaming or low-latency performance.
Use higher (e.g. 2000000) for compute-heavy, background workloads.
2. kernel.sched_wakeup_granularity_ns = 1500000
Default: 1500000 (1.5 milliseconds)
Meaning: Controls how easily a waking task (like an app waiting for input or a network packet) can preempt a currently running one.
- When a sleeping process wakes up, it “asks” to run.
- If it’s given too much priority, it can constantly interrupt other processes, leading to thrashing.
- A smaller value means tasks can preempt sooner — improving input latency (good for gaming, real-time), but may hurt overall throughput.
Tuning tip:
Lowering this to around 1000000 improves latency; keep it balanced with sched_min_granularity_ns.
3. kernel.sched_child_runs_first = 0
Default: 0 (off)
Meaning: Controls whether a new child process (created via fork()) should immediately run before the parent continues.
- When
1, child processes run right away after being created. - When
0, the parent keeps running and the child waits for its turn. - Keeping it at
0avoids sudden task switches and unexpected performance spikes, especially in fast-spawning workloads.
Tuning tip:
Keep this at 0 for predictable scheduling.
Enable only if your workload heavily relies on short-lived child processes.
4. kernel.sched_migration_cost = 500000
Default: 500000 (0.5 ms)
Meaning: Defines how “expensive” it is for the scheduler to move a task between CPU cores.
- Higher value → the kernel avoids moving processes around, which improves cache locality (data stays in CPU caches longer).
- Lower value → the kernel more aggressively balances load between CPUs, which may improve utilization but reduce cache efficiency.
Tuning tip:
Keep it around 500000 or even slightly higher (1000000) for games or latency-sensitive workloads to reduce CPU core migration jitter.
Reduce it if you want the system to distribute CPU load more evenly for multi-threaded, heavy parallel workloads.
5. kernel.sched_tunable_scaling = 0
Default: 1 or 2 (depends on kernel)
Meaning: Controls automatic scaling of scheduling parameters (like the two above) based on the number of CPUs.
When set to:
0: Static — the same values apply across all CPUs.1: Logarithmic scaling — parameters scale logarithmically with CPU count.2: Linear scaling — parameters scale linearly with CPU count.
Tuning tip:
Set it to 0 when you’re manually tuning scheduler parameters and want consistent performance across all cores, regardless of how many CPUs the system has.
6. kernel.sched_autogroup_enabled = 0
Default: 1 (enabled)
Meaning: Controls “autogrouping” — the kernel’s feature that groups tasks by session (for example, all your desktop apps run in one autogroup).
Autogrouping improves fairness between users or desktop sessions, but can harm real-time or gaming performance because it limits per-task prioritization.
Tuning tip:
Set to 0 to disable autogrouping — this gives your active process (like a game or benchmark) more direct access to CPU time without the kernel trying to “balance fairness.”
This is one of the biggest boosts for low-latency gaming or benchmark accuracy.
Recommended Low-Latency Gaming/Benchmark Values
Here’s a set of values that push Linux to behave more like a “real-time” or “gaming mode” system:
# /etc/sysctl.d/99-performance.conf
kernel.sched_min_granularity_ns = 1000000
kernel.sched_wakeup_granularity_ns = 1000000
kernel.sched_child_runs_first = 0
kernel.sched_migration_cost = 1000000
kernel.sched_tunable_scaling = 0
kernel.sched_autogroup_enabled = 0
Apply with:
sudo sysctl -p /etc/sysctl.d/99-performance.conf
Summary
| Parameter | Purpose | Recommended for Performance |
|---|---|---|
sched_min_granularity_ns |
Minimum task run time | 1000000 |
sched_wakeup_granularity_ns |
Wakeup latency | 1000000 |
sched_child_runs_first |
Control fork behavior | 0 |
sched_migration_cost |
CPU migration delay | 1000000 |
sched_tunable_scaling |
Disable scaling | 0 |
sched_autogroup_enabled |
Disable autogroup | 0 |