How to Optimize SA-MP Server: Performance, Tickrate, and Desync
Technical guide to optimizing a SA-MP server: server.cfg tuning, gamemode profiling, essential plugins, and kernel tweaks to eliminate lag and desync.
SA-MP servers with 50 or more concurrent players tend to accumulate three predictable symptoms: tickrate drops during intense combat, desync in car chases, and momentary freezes when many players join at once. In most cases the bottleneck isn’t the host CPU — it’s poorly written loops in the gamemode, outdated plugins, and conservative server.cfg parameters that were never revisited after the initial deploy.
This guide is for you if you administer a SA-MP or open.mp server in production, have SSH access to the host, and know how to recompile a Pawn gamemode. Estimated time for full execution: 90 to 120 minutes, including before-and-after measurements. Each section is independent — you can apply only the parts relevant to your scenario.
The difference between a server that holds 200 slots at peak hour and one that stutters with 60 is rarely hardware. It’s configuration.
Prerequisites
You need SSH access to the server (Ubuntu 22.04 or Debian 12 recommended), sudo permission, the gamemode in .pwn source form (not just compiled .amx), and a maintenance window of at least 30 minutes for a controlled restart. Players should be warned beforehand — connection drops are expected during the final adjustments.
Check the current state before changing anything. Record these numbers — without a baseline, you can’t prove that the optimization worked:
0.3.7-R5 / open.mp 1.4 maxplayers in server.cfg console / showplayercount htop at 80%+ slots Tuning server.cfg
server.cfg is the cheapest place to gain performance — changes here don’t require recompiling anything and can reduce desync within minutes. Most servers still run with default values inherited from 2014-era tutorials that no longer make sense on modern hardware.
Open the configuration file at the server root:
cd /home/samp/server
nano server.cfgLocate the sleep, lagcompmode, playertimeout, and stream_distance lines. If any of these lines is missing, add it — the default values of the SA-MP binary tend to be too conservative for busy servers.
Apply the recommended values for an active server with 100+ slots:
sleep 5
lagcompmode 1
playertimeout 10000
stream_distance 300.0
stream_rate 1000
maxnpc 0
onfoot_rate 30
incar_rate 30
weapon_rate 30sleep 5 reduces the CPU consumed by the main loop without hurting responsiveness. lagcompmode 1 is the modern default for servers with shootouts — change to 2 only if your mechanics are predominantly vehicle chases without combat. playertimeout 10000 (10 seconds) prevents false disconnects on players with occasional jitter.
Changing lagcompmode breaks the perceived behavior of weapons and vehicles. Test on a staging server with at least 20 players before applying to production — players accustomed to the old mode will complain about “shots that don’t hit” for a few days even if the change is technically correct.
Save, exit, and restart the server:
systemctl restart samp-serverIf you don’t use systemd, kill the samp03svr process and restart via screen or tmux. Wait 30 seconds and verify it came up properly:
tail -n 50 server_log.txtAuditing the Pawn gamemode
The biggest source of lag on established SA-MP servers is old gamemode code — especially for(new i = 0; i < MAX_PLAYERS; i++) loops running inside 100ms timers. Each of those loops, multiplied by the timer frequency, can consume more CPU than all plugins combined.
Search for MAX_PLAYERS loops in frequent callbacks:
grep -rn "MAX_PLAYERS" gamemodes/*.pwn | grep -v "Iter_"Each result is a refactor candidate. Rule of thumb: if the loop sits inside a timer or OnPlayerUpdate, it needs to be replaced by foreach iteration (Iter plugin) that iterates only over connected players, not all 1000 possible slots.
Replace MAX_PLAYERS loops with the Iter plugin foreach:
// Before — iterates over 1000 slots even with 50 players
for(new i = 0; i < MAX_PLAYERS; i++)
{
if(IsPlayerConnected(i))
{
// logic
}
}
// After — iterates only over connected players
foreach(new i : Player)
{
// logic
}On a server with 50 active players and MAX_PLAYERS 1000, that’s a 95% reduction in iterations per call. In a 1-second timer, that’s 950 unnecessary checks eliminated on every run.
Audit timers with intervals below 1000ms:
grep -rn "SetTimer" gamemodes/*.pwn100ms timers for tasks that don’t need that frequency (HUD updates, score syncing, position saving) are a common cause of high CPU. Bump them to 500ms or 1000ms where possible. Player position saving to the database should never run below 30 seconds per player.
The Profiler plugin generates a report of time spent per callback during a real session. Load it in staging for 1 hour with real players, generate the report, and prioritize refactors by the top 10 most expensive callbacks. Optimizing code that doesn’t show up in the profile is wasted effort.
Updating essential plugins
SA-MP plugins have a direct impact on CPU consumption and perceived latency. Old versions of streamer and sscanf can cost up to 10 times more per call than current versions — and nearly every established server runs binaries compiled 5 or more years ago.
| Plugin | Recommended minimum | What it improves |
|---|---|---|
| streamer | v2.9.6 | Iteration over dynamic objects, areas, and pickups |
| sscanf | 2.13.8 | Command parsing with multiple parameters |
| MySQL | R41-5 or higher | Asynchronous queries, connection pooling |
| Pawn.RakNet | 1.5+ | Low-overhead RPC packet interception |
| YSF | open.mp DC | Server functions missing from the base binary |
| Profiler | latest available | Staging only — never run in production |
Download the current versions and replace them in the plugins directory:
cd /home/samp/server/plugins
ls -laBack up the old binaries before replacing. Recompile the gamemode with includes matching the new versions — skipping this step causes crashes on calls whose signatures changed between versions.
Adjust the load order in server.cfg. Order matters because plugins depend on each other:
plugins streamer sscanf mysql Pawn.RakNet YSFstreamer always first, MySQL before any plugin that runs a query on startup, YSF last because it hooks functions from other plugins.
Network tuning on the host
The host operating system has kernel parameters that directly affect UDP latency — the protocol used by SA-MP. Linux defaults are optimized for long-lived TCP, not for the many small, frequent packets pattern of SA-MP.
Edit the network parameters in sysctl:
sudo nano /etc/sysctl.d/99-samp.confAdd these values:
net.core.rmem_max = 26214400
net.core.wmem_max = 26214400
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.netdev_max_backlog = 5000
net.ipv4.udp_mem = 8388608 12582912 16777216These values increase UDP receive and transmit buffers, preventing packet drops during traffic bursts (simultaneous player joins, mass events).
Apply without restarting the server:
sudo sysctl -p /etc/sysctl.d/99-samp.confVerify the values were applied:
sysctl net.core.rmem_maxOutput should show the number you set. If it reverts to the default, another sysctl file is overriding — check /etc/sysctl.conf and /etc/sysctl.d/.
On virtualized environments without full privileges, some of these parameters are blocked by the host. Forcing them can result in instance isolation. Dedicated servers or VPS with full KVM accept all the adjustments. If in doubt, consult the provider’s support before changing kernel parameters.
Verification
Confirm improvements with objective measurements. Without before-and-after numbers, it’s impossible to distinguish real optimization from placebo.
Connect 30 to 50 real players or test bots for 30 minutes and record:
htop
CPU consumed by the samp03svr process should sit below 40% of one core under normal load. Memory should be stable — continuous growth indicates a leak in the gamemode, usually in dynamic variables that aren’t deallocated.
For player-perceived latency, use the /ping command in-game or watch the PING column in /players. Pings consistently below 80ms for Brazilian players indicate a healthy network. Variation greater than 30ms between samples indicates jitter — a routing issue, not a server one.
Troubleshooting
Server crashes after updating plugins
Recompile the gamemode with includes matching the new plugin versions. Function signatures change between releases — calling an old function with new arguments causes a stack error that brings the process down. Check the crashlog at crashinfo.txt in the server root.
CPU remains high after refactor
Run the Profiler in staging for 1 hour with real players and identify callbacks that weren’t refactored. Residual loops in OnPlayerUpdate (called dozens of times per second per player) consume CPU exponentially — that callback should never contain loops over all players.
Desync persists even with the correct lagcompmode
Check route packet loss with mtr -r -c 100 SERVER_IP from your computer. Any hop with loss above 0.5% indicates a datacenter network issue or transit problem. This kind of desync has no software fix — it requires changing provider or route.
Next steps
With the server optimized, consider these next technical investments:
- Migrate to open.mp if you’re still on SA-MP 0.3.7-R5 — recompilation costs hours, performance and security gains are permanent.
- Implement server-side anti-cheat with Pawn.RakNet — blocks 90% of common hacks without client dependency.
- Monitor via graphite + grafana or the Hostini panel — watching tickrate and CPU over weeks reveals patterns invisible in point-in-time diagnostics.
- Evaluate dedicated DDoS protection for UDP — attacks against port 7777 are common on popular SA-MP servers.
If you’re hosting a growing SA-MP server, it’s worth considering Hostini’s dedicated game hosting — VPS with full KVM, UDP DDoS protection, and datacenters in São Paulo and Miami with low latency for Brazil and Spanish America. No overselling, no core sharing with other tenants.
Frequently asked questions
What is the ideal tickrate for a SA-MP server with 100 slots?
SA-MP runs at ~25 ticks/second internally, and that's not directly configurable — what you control is the sleep value in server.cfg. Use sleep 5 on active servers to reduce latency without saturating the CPU. Sleep 0 monopolizes the core and rarely pays off outside competitive minigames.
Why does my SA-MP server have desync even with low ping?
Desync at low ping is almost always wrong lagcompmode or intermittent packet loss. Verify lagcompmode 1 in server.cfg, switch to 2 if you have many shootouts/chases. Packet loss above 0.5% on mtr to the server IP indicates a datacenter network issue, not a gamemode problem.
How many SA-MP plugins can I load without losing performance?
There's no hard limit — impact comes from which plugins, not how many. Streamer, sscanf, MySQL R41-5, and Pawn.RakNet combined cost less than 2% CPU on a full server. Old unmaintained plugins (mxINI, legacy foreach) can cost 10x more per call.
Is it worth migrating from SA-MP to open.mp?
Open.mp runs the same Pawn gamemodes compiled for SA-MP 0.3.7-R2 with security fixes and better performance on internal loops. For a new server, start on open.mp. For an established server, test in a parallel environment first — some very old plugins need recompilation.
How do I measure the real impact of each optimization on the SA-MP server?
Use GetTickCount() before and after the block you're optimizing, log it, and compare with a full server. For serious profiling, the YSF Profiler plugin generates a time-per-callback report. Host metrics (CPU, network) come from the Hostini panel or htop/iftop on the server.
How much RAM does a SA-MP server need per slot?
SA-MP itself consumes 50-200 MB regardless of slots. The real RAM cost comes from the gamemode: each dynamic vehicle, pickup, and 3D marker in the streamer uses memory. For 200 slots with a full roleplay system, reserve 1 GB. For freeroam/DM, 512 MB is enough.