Unknown ❤ RESPAWN.ZAFEST.RO | VIP FREE | FREE FOR ALL ❤ 0/32
Romania XPlayZM.CSBlackDevil.COM # Zombie Plague UltimateX [ Respawn + FDL + VIP 22-12PM + POINTS] ® 15/32
Server bewerben

Add 2 tutorials (2 files)

Browse Source
Daemon666 committed parent 82744d8e4d commit 75b54c2e7dffab130d568c9c1b9ccc96c960917b
2 changed files with 26 additions and 0 deletions
+14 -0 cpu-affinity-taskset-hlds/en.md A
@@ -0,0 +1,14 @@
1 +---
2 +title: "Pinning HLDS to a CPU Core with taskset"
3 +excerpt: "How to pin an HLDS or ReHLDS instance to a specific CPU core with taskset for better cache locality, and why it matters most when packing many servers on one box."
4 +category: "optimization"
5 +tags: "cpu, affinity"
6 +image: ""
7 +read_time: "8 min read"
8 +---
9 +<p>By default the Linux scheduler is free to bounce your HLDS process from core to core. For a single-threaded, latency-sensitive game server that is mildly wasteful &mdash; every migration means a cold cache on the new core &mdash; and on a box running several servers it is genuinely harmful, because instances end up fighting over the same cores while others sit idle. <code>taskset</code> fixes both by pinning each server to a core you choose. Here is how to use it correctly.</p><h2>1. See your cores first</h2><p>Know how many cores you have and how they are numbered before pinning:</p><pre>nproc
10 +lscpu | grep -E 'CPU\(s\)|Thread|Core'</pre><p>Cores are numbered from <code>0</code>. On a 4-core box you have <code>0,1,2,3</code>. Note whether hyper-threading is on &mdash; sibling threads share a physical core, so pinning two busy servers to two siblings is not the same as two real cores.</p><h2>2. Launch a server pinned to a core</h2><p>Wrap the launch command with <code>taskset -c</code> and the core number:</p><pre>taskset -c 2 ./hlds_run -game cstrike +ip 0.0.0.0 +port 27015 +map de_dust2 +maxplayers 32</pre><p><code>-c 2</code> confines the process (and its threads) to core 2. Everything the server spawns inherits that affinity. Reserve core <code>0</code> for the OS and interrupts where you can, and give servers cores <code>1</code> and up.</p><h2>3. Pin a server that is already running</h2><p>You do not have to restart to pin. Find the PID and set affinity live with <code>-p</code>:</p><pre>pgrep -a hlds
11 +taskset -cp 2 12345 # 12345 = the hlds_linux PID</pre><p>Read the current affinity back the same way without a core list:</p><pre>taskset -cp 12345
12 +# pid 12345's current affinity list: 2</pre><p>Note that the real game process is often <code>hlds_linux</code> under the <code>hlds_run</code> wrapper &mdash; pin the actual <code>hlds_linux</code> PID, not just the shell wrapper.</p><h2>4. Why pinning helps</h2><p>Two concrete wins:</p><ul><li><strong>Cache locality</strong> &mdash; a server that stays on one core keeps its working set warm in that core's L1/L2 cache. A migration to another core starts cold and costs cycles right when the server is busy.</li><li><strong>Deterministic packing</strong> &mdash; when you <a href="/tutorials/multiple-cs16-servers-one-vps">run many servers on one box</a>, pinning server A to core 1, B to core 2, C to core 3 guarantees they never pile onto the same core and starve each other. Left to the scheduler, two servers can end up on one core while a third sits empty.</li></ul><p>The effect is small for a single lightly-loaded server and large for a dense multi-server box &mdash; that is where <code>taskset</code> earns its keep.</p><h2>5. Pair affinity with IRQ placement</h2><p>Pinning the game to a core only helps if that core is not also being hammered by network interrupts. On a busy server the NIC generates a lot of hardware interrupts, and if those land on the same core as your server they compete for it. Two complementary moves keep them apart. First, dedicate a core (or the OS default core 0) to interrupts and keep your servers off it. Second, on multi-queue NICs you can steer the interrupts explicitly by writing an affinity mask to each queue's IRQ:</p><pre>grep eth0 /proc/interrupts # find the NIC's IRQ numbers
13 +cat /proc/irq/&lt;irq&gt;/smp_affinity_list</pre><p>The principle is simple: let one core handle NIC interrupts and the OS, and give each game server its own separate core. That way the server's core spends its time on the game loop and nothing else &mdash; which is the entire point of pinning in the first place.</p><h2>6. Make it stick across restarts</h2><p>Affinity set with <code>taskset -cp</code> is lost when the process restarts, so bake it into how the server launches. Either prefix the launch command in your start script with <code>taskset -c N</code>, or if you run under systemd use the built-in directive:</p><pre># in the [Service] section of your unit file
14 +CPUAffinity=2</pre><p>systemd then pins the service to core 2 every start, no wrapper needed. Reload with <code>systemctl daemon-reload</code> and restart the unit.</p><h2>Common mistakes</h2><ul><li><strong>Pinning the wrapper, not the game</strong> &mdash; <code>hlds_run</code> is a shell script; confirm the actual <code>hlds_linux</code> PID carries the affinity.</li><li><strong>Pinning everything to core 0</strong> &mdash; core 0 also handles OS work and interrupts. Leave it for the system; use cores 1+ for servers.</li><li><strong>Treating HT siblings as real cores</strong> &mdash; two hyper-threads share one physical core; pinning two busy servers there does not double throughput.</li><li><strong>Expecting a big single-server gain</strong> &mdash; the win is cache locality and packing, not a magic FPS boost on an idle box.</li><li><strong>Losing affinity on restart</strong> &mdash; <code>-cp</code> is runtime-only. Put <code>taskset</code> in the launch command or use <code>CPUAffinity=</code>.</li></ul><h2>Verification</h2><p>Confirm the pin took and holds. Read affinity back with <code>taskset -cp &lt;pid&gt;</code> &mdash; it should list exactly the core you set. Then run <code>top</code>, press <code>1</code> for per-core view, and watch under load: the server's CPU should appear on your chosen core and stay there instead of hopping between cores. On a multi-server box, confirm each instance sits on its own core with none doubled up. Pair this with the <a href="/tutorials/cpu-governor-performance"><code>performance</code> governor</a> so the pinned core also runs at full clock, and with a <a href="/tutorials/best-cpu-for-cs16-server">fast single-thread CPU</a> so that core is worth pinning to.</p>
+12 -0 kernel-timer-hz-linux/en.md A
@@ -0,0 +1,12 @@
1 +---
2 +title: "Kernel Timers, HZ and CONFIG_HZ_1000 for Game Servers"
3 +excerpt: "How the Linux timer tick historically limited HLDS fps, why CONFIG_HZ_1000 mattered, and how modern high-resolution timers and ReHLDS changed the picture without eliminating jitter."
4 +category: "optimization"
5 +tags: "kernel, linux"
6 +image: ""
7 +read_time: "8 min read"
8 +---
9 +<p>There is a long-standing belief that you must recompile your kernel with <code>CONFIG_HZ_1000</code> 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 <em>why</em> the kernel timer ever mattered lets you decide whether it is worth touching on your box &mdash; and stops you cargo-culting a kernel rebuild that a modern <a href="/tutorials/hlds-vs-rehlds-explained">ReHLDS</a> install does not need.</p><h2>1. What the HZ value is</h2><p>The kernel's <code>CONFIG_HZ</code> sets the frequency of the periodic timer interrupt &mdash; how often the scheduler wakes up to make decisions. Common values are <code>100</code>, <code>250</code>, <code>300</code> and <code>1000</code> Hz. Check yours:</p><pre>grep CONFIG_HZ /boot/config-$(uname -r)</pre><p>Historically this value was also the granularity of <code>usleep()</code> / <code>nanosleep()</code>: 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 <code>CONFIG_HZ_1000</code> became folklore for HLDS boxes.</p><h2>2. Why high-resolution timers changed this</h2><p>Modern Linux kernels ship <strong>high-resolution timers</strong> (<code>hrtimers</code>) and <code>NO_HZ</code> / tickless operation. With hrtimers, <code>nanosleep()</code> no longer rounds to the <code>CONFIG_HZ</code> boundary &mdash; it can resolve to microseconds regardless of the periodic tick frequency. Verify hrtimers are active:</p><pre>cat /proc/timer_list | grep resolution
10 +cat /sys/devices/system/clocksource/clocksource0/current_clocksource</pre><p>You want a <code>tsc</code> or <code>hpet</code> clocksource and nanosecond resolution. On such a kernel, the old hard link between <code>CONFIG_HZ</code> and achievable fps is largely broken &mdash; the engine can pace itself finely without a 1000 Hz periodic tick.</p><h2>3. What ReHLDS does differently</h2><p>Stock HLDS relied on the engine's <a href="/tutorials/sys-ticrate-truth">sys_ticrate</a> 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 <code>CONFIG_HZ</code>. This is why the practical advice today is "run ReHLDS on a recent kernel" rather than "recompile with HZ 1000". See <a href="/tutorials/stable-1000-fps-linux-server">the stable 1000 fps guide</a> for the engine-side settings that actually move the needle now.</p><h2>4. Where the HZ value still matters: jitter</h2><p>Even with hrtimers, the <em>periodic</em> tick still governs how often the scheduler can preempt and re-balance. On a heavily loaded box running multiple instances, a higher <code>CONFIG_HZ</code> reduces scheduling latency and therefore frame-time jitter &mdash; the fps average may be fine on any HZ, but the <em>consistency</em> 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.</p><h2>5. Practical tuning that beats a kernel rebuild</h2><p>Before recompiling anything, get the cheap wins:</p><pre>cpupower frequency-set -g performance
11 +cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor</pre><p>Force the <a href="/tutorials/cpu-governor-performance">performance CPU governor</a> so cores do not downclock between frames &mdash; a downclocking core causes far more fps jitter than a suboptimal HZ value ever will. Then pin instances with <a href="/tutorials/cpu-affinity-taskset-hlds">taskset</a> 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 <code>CONFIG_HZ</code>.</p><h2>Common errors</h2><ul><li><strong>Recompiled kernel to HZ 1000, no fps change</strong> &mdash; hrtimers already gave fine sleep resolution; the bottleneck was the governor or the engine, not the tick.</li><li><strong>fps average fine but visibly stuttery under load</strong> &mdash; scheduling jitter. Pin instances and force the performance governor before blaming HZ.</li><li><strong>Cannot check CONFIG_HZ</strong> &mdash; on a VPS you often cannot change it anyway (shared host kernel). Focus on governor, affinity and ReHLDS.</li><li><strong>Clocksource is not tsc/hpet</strong> &mdash; a poor clocksource (e.g. <code>acpi_pm</code>) hurts timing; investigate why the kernel fell back.</li><li><strong>Expecting HZ to raise a single server's ceiling</strong> &mdash; the ceiling is single-core speed and engine timing, not the periodic tick.</li></ul><h2>Verification</h2><p>Check your clocksource and governor, then measure real server fps under load:</p><pre>cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
12 +stats</pre><p>A <code>performance</code> governor plus a stable <code>fps</code> reading near your target on a modern kernel means the timer subsystem is not your problem &mdash; do not rebuild the kernel chasing a myth. If fps is unstable, confirm with <a href="/tutorials/measure-server-fps">the fps measurement guide</a> and work through <a href="/tutorials/sys-ticrate-truth">the sys_ticrate truth</a> and <a href="/tutorials/fix-low-server-fps-linux">low server fps on Linux</a> before touching <code>CONFIG_HZ</code>. 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 &mdash; and on modern hardware it is enough.</p>
0 13