Kernel Timers, HZ and CONFIG_HZ_1000 for Game Servers

November 6, 2025 Daemon666 8 min read

There is a long-standing belief that you must recompile your kernel with CONFIG_HZ_1000 to run a smooth 1000 fps CS 1.6 server. On older systems that was genuinely true; on modern kernels the story is more nuanced. Understanding why the kernel timer ever mattered lets you decide whether it is worth touching on your box — and stops you cargo-culting a kernel rebuild that a modern ReHLDS install does not need.

1. What the HZ value is

The kernel's CONFIG_HZ sets the frequency of the periodic timer interrupt — how often the scheduler wakes up to make decisions. Common values are 100, 250, 300 and 1000 Hz. Check yours:

grep CONFIG_HZ /boot/config-$(uname -r)

Historically this value was also the granularity of usleep() / nanosleep(): on a 100 Hz kernel a sleep could only resolve to ~10 ms boundaries, so a game loop that slept between frames could not pace itself finely enough to hit a steady 1000 fps. A 1000 Hz kernel gave 1 ms granularity, which is why CONFIG_HZ_1000 became folklore for HLDS boxes.

2. Why high-resolution timers changed this

Modern Linux kernels ship high-resolution timers (hrtimers) and NO_HZ / tickless operation. With hrtimers, nanosleep() no longer rounds to the CONFIG_HZ boundary — it can resolve to microseconds regardless of the periodic tick frequency. Verify hrtimers are active:

cat /proc/timer_list | grep resolution
cat /sys/devices/system/clocksource/clocksource0/current_clocksource

You want a tsc or hpet clocksource and nanosecond resolution. On such a kernel, the old hard link between CONFIG_HZ and achievable fps is largely broken — the engine can pace itself finely without a 1000 Hz periodic tick.

3. What ReHLDS does differently

Stock HLDS relied on the engine's sys_ticrate and coarse sleeps, which is exactly the code that suffered on low-HZ kernels. ReHLDS rewrote the timing loop to use finer sleeps and better frame pacing, so on a modern kernel it can hold high, stable fps largely independent of CONFIG_HZ. This is why the practical advice today is "run ReHLDS on a recent kernel" rather than "recompile with HZ 1000". See the stable 1000 fps guide for the engine-side settings that actually move the needle now.

4. Where the HZ value still matters: jitter

Even with hrtimers, the periodic tick still governs how often the scheduler can preempt and re-balance. On a heavily loaded box running multiple instances, a higher CONFIG_HZ reduces scheduling latency and therefore frame-time jitter — the fps average may be fine on any HZ, but the consistency improves with a higher tick and with a tickless-idle configuration that keeps busy cores responsive. For a single lightly loaded server the difference is negligible; for a box packed with servers it can be the difference between smooth and periodically stuttery.

5. Practical tuning that beats a kernel rebuild

Before recompiling anything, get the cheap wins:

cpupower frequency-set -g performance
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

Force the performance CPU governor so cores do not downclock between frames — a downclocking core causes far more fps jitter than a suboptimal HZ value ever will. Then pin instances with taskset so scheduler migrations do not disturb frame pacing. On most modern VPSes, governor plus affinity plus ReHLDS gets you a stable 1000 fps without ever touching CONFIG_HZ.

Common errors

  • Recompiled kernel to HZ 1000, no fps change — hrtimers already gave fine sleep resolution; the bottleneck was the governor or the engine, not the tick.
  • fps average fine but visibly stuttery under load — scheduling jitter. Pin instances and force the performance governor before blaming HZ.
  • Cannot check CONFIG_HZ — on a VPS you often cannot change it anyway (shared host kernel). Focus on governor, affinity and ReHLDS.
  • Clocksource is not tsc/hpet — a poor clocksource (e.g. acpi_pm) hurts timing; investigate why the kernel fell back.
  • Expecting HZ to raise a single server's ceiling — the ceiling is single-core speed and engine timing, not the periodic tick.

Verification

Check your clocksource and governor, then measure real server fps under load:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
stats

A performance governor plus a stable fps reading near your target on a modern kernel means the timer subsystem is not your problem — do not rebuild the kernel chasing a myth. If fps is unstable, confirm with the fps measurement guide and work through the sys_ticrate truth and low server fps on Linux before touching CONFIG_HZ. On a VPS you frequently share the host's kernel and cannot recompile it at all, which makes the governor-and-affinity route not just easier but the only one available — and on modern hardware it is enough.

Участники: Daemon666 ✦
Поделиться: