Add 2 tutorials (2 files)
Browse Source
2 changed files
with 35 additions and 0 deletions
benchmark-monitor-cs16-server/en.md
A
| @@ -0,0 +1,18 @@ | ||
| 1 | +--- | |
| 2 | +title: "Tools to Benchmark and Monitor a CS 1.6 Server" | |
| 3 | +excerpt: "The Linux tools that tell you whether a CS 1.6 server is healthy, from server FPS and CPU per-core load to network counters and steal time, with the exact commands." | |
| 4 | +category: "optimization" | |
| 5 | +tags: "monitoring, tools" | |
| 6 | +image: "" | |
| 7 | +read_time: "8 min read" | |
| 8 | +--- | |
| 9 | +<p>You cannot optimize what you cannot measure. Before you touch a single cvar, you need numbers: what the server FPS actually is, which core is loaded, whether the box is losing packets, and whether the hypervisor is stealing your CPU. This is the practical toolkit — standard Linux utilities plus the two in-game commands — that tells you where a CS 1.6 server actually hurts.</p><h2>1. Server FPS: the in-game number that matters most</h2><p>The single most important performance metric is the server's frame rate, because it caps how smooth movement and hit registration feel. Read it from the server console:</p><pre>stats</pre><p>The <code>fps</code> field is your headline number. A healthy <a href="/tutorials/sys-ticrate-truth"><code>sys_ticrate</code></a>-driven server holds a steady 500–1000; if it sags under load, that is your bottleneck. The full method, including how to log it over time, is in <a href="/tutorials/measure-server-fps">measuring server FPS</a>.</p><h2>2. top and htop: per-core CPU</h2><p>HLDS/ReHLDS is single-threaded per instance, so aggregate CPU is misleading — you care about the one core it runs on. In <code>top</code>, press <code>1</code> to expand per-core lines:</p><pre>top | |
| 10 | +# press 1 to show every core separately</pre><p>One core pinned near 100% while others idle is normal and expected for one server — that is <a href="/tutorials/is-hlds-single-threaded">the single-thread reality</a>, not a bug. Watch the <code>%us</code> (user) column for the hlds process. Also watch <code>%st</code> (steal) on a VPS — more on that below. <code>htop</code> gives the same data with a nicer per-core bar display.</p><h2>3. Watch steal time explicitly</h2><p>On a VPS, the number that silently ruins performance is steal. Two ways to see it:</p><pre>vmstat 1 | |
| 11 | +# the 'st' column, far right | |
| 12 | + | |
| 13 | +mpstat -P ALL 1 | |
| 14 | +# per-core %steal</pre><p>Any sustained non-zero <code>st</code> means the hypervisor is handing your vCPU to another tenant; the full diagnosis is in <a href="/tutorials/cpu-steal-time-vps">CPU steal time</a>. On a healthy dedicated box this is always zero.</p><h2>4. Network: choke, loss and interface counters</h2><p>Distinguish server-side choke from real network loss. In-game, the scoreboard shows per-player <code>choke</code> and <code>loss</code>; on the box, watch the interface and sockets:</p><pre>ifstat 1 # per-second in/out per interface | |
| 15 | +ss -u -a -n | grep 27015 # UDP sockets on the game port | |
| 16 | +ip -s link show eth0 # RX/TX errors and drops</pre><p>Rising <code>RX dropped</code> or <code>errors</code> on <code>ip -s link</code> points at the NIC or kernel buffers; per-player <code>choke</code> on the scoreboard points at <a href="/tutorials/sv-maxrate-maxupdaterate-values">rate settings</a> instead. Keep the two separate — see <a href="/tutorials/fix-choke-loss-scoreboard">choke vs loss</a>.</p><h2>5. Latency and path quality: mtr</h2><p>For anything ping- or loss-related from the outside, run a continuous traceroute from a client toward the server:</p><pre>mtr --report --report-cycles 100 YOUR.SERVER.IP</pre><p>Read the <code>Loss%</code> and <code>Avg</code> columns per hop; loss that appears mid-path but clears at the final hop is usually ICMP rate-limiting, not real loss. The full reading guide is in <a href="/tutorials/diagnose-packet-loss-vps">diagnosing packet loss</a>.</p><h2>6. Keep history, not just snapshots</h2><p>Live tools show now; problems happen at 9pm when you are asleep. Log trends:</p><pre>vnstat -i eth0 # daily/monthly traffic totals | |
| 17 | +sar -u 1 3 # CPU history via sysstat | |
| 18 | +apt install sysstat vnstat</pre><p><code>sar</code> (from the sysstat package) records CPU, load and network to disk so you can look back at what the box was doing during last night's lag spike. Pair it with an external <a href="/tutorials/monitor-server-uptime-alerts">uptime monitor</a> so you are alerted when the server drops rather than finding out from angry players.</p><h2>Common mistakes</h2><ul><li><strong>Judging load by total CPU%</strong> — a quad-core at 25% total can have one core pegged. Press <code>1</code> in <code>top</code> and read per-core.</li><li><strong>Ignoring <code>%st</code></strong> — steal does not show in aggregate load; it is CPU you paid for and did not get.</li><li><strong>Blaming the network for choke</strong> — scoreboard <code>choke</code> is the server hitting a rate cap, not packet loss on the wire.</li><li><strong>Only looking live</strong> — without <code>sar</code>/<code>vnstat</code> history you cannot diagnose a spike that already passed.</li></ul><h2>Verification</h2><p>Build a one-screen baseline while the server is busy: <code>stats</code> in the game console for FPS, <code>top</code> with per-core view for the pinned core and <code>%st</code>, <code>ifstat 1</code> for throughput, and an <code>mtr</code> from a client. Record those four numbers when the server is healthy. Next time players report lag, re-read the same four — whichever one moved is your culprit, and it points straight at the matching fix: low FPS to <a href="/tutorials/fix-low-server-fps-linux">server FPS tuning</a>, high steal to a <a href="/tutorials/cpu-steal-time-vps">better host</a>, choke to rate cvars, path loss to the network.</p> |
improve-hit-registration/en.md
A
| @@ -0,0 +1,17 @@ | ||
| 1 | +--- | |
| 2 | +title: "Improving Hit Registration on Your Server" | |
| 3 | +excerpt: "How GoldSrc lag compensation actually works, the sv_unlag cvars that govern it, and the combination of stable server fps, sane rates and low choke that makes shots land where the crosshair was." | |
| 4 | +category: "optimization" | |
| 5 | +tags: "hitreg, netcode" | |
| 6 | +image: "" | |
| 7 | +read_time: "8 min read" | |
| 8 | +--- | |
| 9 | +<p>"Hitreg feels off" is the most common complaint on a busy CS 1.6 server, and unlike aim it is often genuinely fixable from the server side. GoldSrc uses <strong>server-side lag compensation</strong>: when a client fires, the server rewinds every other player to where they were on the shooter's screen at the moment of the shot, then tests the bullet against those rewound positions. Get the inputs to that system right and shots land; get them wrong and players empty a magazine into a body for no damage. There is no magic cvar — it is a chain, and every link matters.</p><h2>1. Confirm lag compensation is on</h2><p>The rewind system is controlled by a family of cvars. The defaults are usually correct, but verify them:</p><pre>sv_unlag 1 | |
| 10 | +sv_maxunlag 0.5 | |
| 11 | +sv_unlagpush 0 | |
| 12 | +sv_unlagsamples 1</pre><p><code>sv_unlag 1</code> enables compensation — turning it off is almost always wrong on a public server. <code>sv_maxunlag 0.5</code> caps how far back (in seconds) the server will rewind, which bounds abuse from very high-latency clients. Leave <code>sv_unlagpush</code> at <code>0</code> unless you are chasing a specific edge case; nudging it changes how positions are interpolated and usually makes things worse, not better.</p><h2>2. Run a stable, high server fps</h2><p>Lag compensation rewinds to stored position snapshots, and the resolution of those snapshots depends on how often the server ticks. A server juddering between 100 and 400 fps stores irregular history, so the rewind lands between real positions and the hit test misses the edge of a model. A rock-solid ~1000 fps gives dense, evenly spaced history and dramatically tighter registration. This is why <a href="/tutorials/stable-1000-fps-linux-server">a stable 1000 fps</a> matters for hitreg specifically, not just for feel. Confirm it with <a href="/tutorials/measure-server-fps">the fps measurement guide</a> and the console:</p><pre>stats</pre><h2>3. Kill choke and loss first</h2><p>Compensation cannot rewind to a snapshot the client never received. If clients are choking or losing packets, their view of enemy positions is stale, the server rewinds to the wrong place, and hits vanish. Eliminate choke with a correct <a href="/tutorials/eliminate-choke-server">sv_maxupdaterate configuration</a> and watch loss on <a href="/tutorials/cs16-net-graph-guide">net_graph</a>. Clean netcode is a precondition for good hitreg, not a separate concern.</p><h2>4. Get client rates and interpolation right</h2><p>The server rewinds to the position the shooter <em>saw</em>, and what the shooter saw is set by their interpolation. Advise players toward consistent values:</p><pre>cl_updaterate 100 | |
| 13 | +cl_cmdrate 100 | |
| 14 | +rate 25000 | |
| 15 | +ex_interp 0.01</pre><p>An <code>ex_interp</code> that fights the update rate (too high with a high updaterate) makes the client render enemies further in the past than the server expects to rewind, spreading hits. Pair a 100 updaterate with a small interp. The full table is in <a href="/tutorials/cs16-best-client-rates">best client rates</a>.</p><h2>5. Prefer ReHLDS for consistency</h2><p>The reverse-engineered <a href="/tutorials/hlds-vs-rehlds-explained">ReHLDS</a> engine holds a steadier frame time under load than stock HLDS, and steadier frame time means more uniform lag-compensation history. It is not a hitreg cheat — it will not make a missed shot hit — but it removes a class of jitter-induced misses that plague loaded HLDS servers. The <a href="/tutorials/rehlds-performance-cvars">ReHLDS performance cvars</a> let you tune the timing further.</p><h2>Common errors</h2><ul><li><strong>Hits fine 1v1, bad on full server</strong> — server fps collapses under load, so the position history degrades. Fix fps and CPU headroom first.</li><li><strong>High-ping players seem to "eat" bullets or trade unfairly</strong> — <code>sv_maxunlag</code> is too high, letting the server rewind very far. Cap it at <code>0.5</code>.</li><li><strong>Shots register late / feel delayed</strong> — client interpolation too high for the update rate. Lower <code>ex_interp</code> toward <code>0.01</code>.</li><li><strong>Everyone's hitreg is bad regardless of ping</strong> — choke or loss on the server. Clean the netcode before touching unlag.</li><li><strong>Disabling sv_unlag to "fix" it</strong> — this makes high-ping players need to lead targets and feels far worse for the majority. Leave it on.</li></ul><h2>Verification</h2><p>Read the unlag cvars back and confirm fps under load:</p><pre>sv_unlag | |
| 16 | +sv_maxunlag | |
| 17 | +stats</pre><p>Then test with a partner: have them strafe at a wall corner while you shoot; damage numbers should track their model tightly with <code>net_graph 3</code> showing zero choke and zero loss on both ends. If registration is tight in that controlled test but poor on a full server, the culprit is fps or CPU under load — work through <a href="/tutorials/fix-server-fps-drops-with-players">fps drops with players</a>. Set expectations honestly with your community: good server config removes bad hitreg, it does not turn misses into hits, and no server on earth can compensate for a player's own 150 ms connection to the box. What you can guarantee is that the server never adds error of its own.</p> | |
| 0 | 18 |









