---
title: "How to Measure Real Server FPS (stats and ReHLDS Tools)"
excerpt: "Server FPS is the tick loop rate, not the client frame rate. Here is how to read the real number from the HLDS console, over RCON, and under load."
category: "optimization"
tags: "fps, monitoring"
image: ""
read_time: "7 min read"
---
<p>"Server FPS" has nothing to do with what you see on your screen. On a CS 1.6 dedicated server it is the rate of the engine's main loop — how many times per second the server simulates the world, processes player commands and sends updates. A server pinned at 1000 FPS feels tight and responsive; one that sags to 40 under a full house feels like every shot lands late. Before you tune anything, you need to measure the real number honestly, because the target you set with <code>sys_ticrate</code> and the number you actually get are frequently not the same.</p><h2>1. Read it with the stats command</h2><p>The console command <code>stats</code> is built into HLDS and ReHLDS. Type it in the server console (or over RCON) and it prints a single line:</p><pre>stats</pre><p>The output is roughly:</p><pre>CPU In_(KB/s) Out_(KB/s) Uptime Users FPS Players
6.30 2.45 9.81 180 4 999.85 4</pre><p>The column that matters is <strong>FPS</strong>. <code>CPU</code> is the percentage of one core the server is burning, <code>In</code>/<code>Out</code> are bandwidth, and <code>Players</code> is the live count. Run <code>stats</code> a few times a second apart — a single reading tells you almost nothing because FPS fluctuates frame to frame.</p><h2>2. Compare the target against the reality</h2><p>The server tries to run at the rate set by <code>sys_ticrate</code>. Check what you asked for:</p><pre>sys_ticrate</pre><p>If <code>sys_ticrate</code> is 1000 but <code>stats</code> reports 512, or 200, the server cannot sustain the target on this hardware or with this launch configuration. That gap — not the raw number — is the diagnostic. A machine holding a steady 500 FPS is healthier than one that claims to target 1000 and jitters between 300 and 1000.</p><h2>3. Measure over RCON from outside</h2><p>You do not need shell access to the box. From a connected client's console, authenticate and query:</p><pre>rcon_password your_rcon_password
rcon stats</pre><p>This is the honest way to check a server you rent from a host — the panel's "FPS" widget is often the configured <code>sys_ticrate</code>, not the measured value. <code>rcon stats</code> returns the same line the local console does.</p><h2>4. Measure under load, not empty</h2><p>An empty server will happily report its target FPS. The number that matters is the one with a full server mid-round, because every connected player adds work to each frame. If you cannot wait for real players, add bots (for example with <a href="/tutorials/install-yapb-bots">YaPB</a>) to load the CPU, then watch <code>stats</code> during a firefight. A server that reads 1000 empty and 250 with 24 players and bots does not have a 1000 FPS problem — it has a CPU problem.</p><h2>5. Watch CPU alongside FPS</h2><p>The <code>CPU</code> column in <code>stats</code> is the single most useful companion to the FPS number. HLDS is single-threaded, so it can only ever use one core; a reading near 100 means that core is saturated and FPS will fall no matter what <code>sys_ticrate</code> says. On Linux, confirm from the shell:</p><pre>top -p $(pgrep -f hlds_linux)</pre><p>If <code>hlds_linux</code> sits at 100% of a core while FPS is below target, the loop is CPU-bound. That points you at the engine (stock HLDS timing), the <code>-pingboost</code> mode, or a heavy plugin — see <a href="/tutorials/fix-hlds-100-cpu">HLDS at 100% CPU</a> and <a href="/tutorials/fix-low-server-fps-linux">low server FPS on Linux</a>.</p><h2>6. ReHLDS reports the same way</h2><p>ReHLDS uses the identical <code>stats</code> command, so nothing about measuring changes. What changes is that ReHLDS keeps far more accurate frame timing than stock HLDS, so a <code>sys_ticrate</code> of 1000 is much more likely to actually be held. If you are chasing a stable high number, the engine swap does more than any cvar — see <a href="/tutorials/rehlds-performance-cvars">ReHLDS performance cvars</a> and <a href="/tutorials/stable-1000-fps-linux-server">getting stable 500/1000 FPS on Linux</a>.</p><h2>Common errors and misreadings</h2><ul><li><strong>Reading FPS from a control panel instead of <code>stats</code></strong> — many panels display the configured tick target, not the measured rate. Always confirm with <code>rcon stats</code>.</li><li><strong>Measuring an empty server and declaring victory</strong> — load changes everything. Measure with players or bots.</li><li><strong>Confusing server FPS with client <code>fps_max</code></strong> — they are unrelated numbers. Boosting your own client does nothing for the server tick; see <a href="/tutorials/cs16-fps-boost-guide">the client FPS guide</a>.</li><li><strong>Expecting a Windows server to hit Linux numbers</strong> — the Windows timer caps sustained FPS far lower; 100–200 is normal there.</li><li><strong>FPS looks fine but players complain of lag</strong> — that is a rate/choke problem, not an FPS problem. Check the scoreboard for loss and choke, covered in <a href="/tutorials/fix-choke-loss-scoreboard">choke and loss on the scoreboard</a>.</li></ul><h2>Verification</h2><p>You have a trustworthy measurement when: <code>stats</code> gives you a stable FPS reading across several samples; that reading is taken with the server under realistic load; and the <code>CPU</code> column is well under 100 at your target rate. Note the empty-server FPS and the full-server FPS separately — those two numbers are what every tuning change should be judged against. With a real baseline in hand, move on to <a href="/tutorials/sv-maxrate-maxupdaterate-values">setting correct rate cvars</a> and, if the number is low, <a href="/tutorials/stable-1000-fps-linux-server">the Linux FPS guide</a>.</p>