Game Server Optimization and Performance Tuning

Game server performance is critical for player experience and infrastructure efficiency. This guide covers CPU affinity optimization, process priority tuning, network parameter optimization, tick rate configuration, memory management, and real-time performance monitoring. Proper optimization can increase server capacity by 30-50% while reducing latency and improving player experience.

Table of Contents

Performance Fundamentals

Game server performance depends on:

  • CPU: Process scheduling and computation
  • Memory: Game state, player data, world data
  • Network: Bandwidth and latency
  • Disk I/O: Save operations and asset loading

Monitor all metrics continuously:

# Quick system overview
top -b -n 1 | head -20

# Memory information
free -h
cat /proc/meminfo

# CPU information
nproc  # Number of cores
lscpu
cat /proc/cpuinfo

# Network statistics
netstat -s
ss -s

# Disk information
df -h
iostat -x 1

CPU Optimization

CPU Affinity (Process Pinning)

Bind server process to specific CPU cores for better cache locality:

# Get server PID
PID=$(pgrep -f "valheim_server\|RustDedicated\|7DaysToDie")
echo "Server PID: $PID"

# Pin to cores 0-3 (quad-core)
taskset -p -c 0-3 $PID
taskset -pc $PID  # Verify

# Pin to cores 0-7 (octa-core)
taskset -p -c 0-7 $PID

# Pin to specific core only (core 0)
taskset -p -c 0 $PID

Create script for automatic CPU affinity:

sudo tee /home/steam/set_cpu_affinity.sh > /dev/null <<'EOF'
#!/bin/bash

# Game server process name
PROCESS_NAME="${1:-valheim_server}"
CORES="${2:-0-3}"

PID=$(pgrep -f "$PROCESS_NAME")

if [ -z "$PID" ]; then
    echo "Process $PROCESS_NAME not found"
    exit 1
fi

echo "Setting CPU affinity for $PROCESS_NAME (PID: $PID) to cores $CORES"
taskset -p -c "$CORES" "$PID"

if [ $? -eq 0 ]; then
    echo "✓ CPU affinity set successfully"
    taskset -pc "$PID"
else
    echo "✗ Failed to set CPU affinity"
fi
EOF

sudo chmod +x /home/steam/set_cpu_affinity.sh

Process Priority (nice/renice)

Adjust process priority to ensure sufficient CPU time:

# Get current nice value (-20 to 19, lower = higher priority)
ps -o pid,nice,comm $(pgrep -f valheim_server)

# Set priority at startup (in service file)
ExecStart=/usr/bin/nice -n -10 /home/steam/valheim/start_server.sh

# Change priority of running process
PID=$(pgrep -f valheim_server)
sudo renice -n -10 $PID

# Set very high priority (use cautiously)
sudo renice -n -20 $PID  # Maximum priority

Add to systemd service:

# Edit service file
sudo nano /etc/systemd/system/valheim.service

# In [Service] section, add:
Nice=-10

CPU Governor and Frequency Scaling

For consistent performance, disable CPU frequency scaling:

# Check current governor
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

# Set to performance mode (all cores at max frequency)
echo "performance" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

# Make permanent in /etc/rc.local
echo 'echo "performance" | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor' | sudo tee -a /etc/rc.local

# Alternative: Use cpufreq-set
sudo apt-get install linux-cpupower
sudo cpupower frequency-set -g performance

Monitor CPU usage:

# Per-core CPU usage
top -i
mpstat -P ALL 1

# Process-specific CPU
watch -n 1 'ps aux | grep valheim_server | grep -v grep | awk "{print \$2, \$3, \$4, \$11}"'

# CPU frequency monitoring
watch -n 1 'grep MHz /proc/cpuinfo'

Memory Optimization

Memory Management

Monitor memory usage:

# Real-time memory monitoring
watch -n 1 free -h

# Process-specific memory
PID=$(pgrep -f valheim_server)
ps -p $PID -o rss=,vsz=,pmem=
smem -p -P valheim_server

# Memory mapping
cat /proc/$PID/maps | head -20

# Memory pressure
cat /proc/pressure/memory

Configure swappiness (how aggressively Linux uses swap):

# Current swappiness (0-100)
cat /proc/sys/vm/swappiness

# Reduce swappiness for game servers (minimize swap usage)
sudo sysctl -w vm.swappiness=10
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf

# Increase swappiness only if swap is needed
sudo sysctl -w vm.swappiness=30

Memory leak detection:

# Monitor memory growth over time
watch -n 5 'ps aux | grep valheim_server | grep -v grep | awk "{print \$2, \$6/1024 \"MB\"}"'

# Create monitoring script
sudo tee /home/steam/monitor_memory_leak.sh > /dev/null <<'EOF'
#!/bin/bash

PID=$(pgrep -f valheim_server)
INTERVAL=60  # Sample every 60 seconds
SAMPLES=1440  # Collect for 24 hours

for i in $(seq 1 $SAMPLES); do
    MEM=$(ps -p $PID -o rss= 2>/dev/null)
    if [ ! -z "$MEM" ]; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') $((MEM/1024)) MB" >> /tmp/memory_log.txt
    fi
    sleep $INTERVAL
done
EOF

sudo chmod +x /home/steam/monitor_memory_leak.sh

Garbage Collection Tuning (for Java servers)

For game servers using Java:

# Optimal JVM options for low-latency servers
JAVA_OPTS="-Xms8G -Xmx8G \
    -XX:+UseG1GC \
    -XX:MaxGCPauseMillis=200 \
    -XX:InitiatingHeapOccupancyPercent=35 \
    -XX:G1HeapRegionSize=16M \
    -XX:MinMetaspaceExpansion=21M \
    -XX:MaxMetaspaceExpansion=256M"

Network Optimization

System-Level Network Tuning

Optimize kernel network parameters for game server performance:

# Increase socket buffer sizes
sudo sysctl -w net.core.rmem_max=134217728
sudo sysctl -w net.core.wmem_max=134217728
sudo sysctl -w net.core.rmem_default=131072
sudo sysctl -w net.core.wmem_default=131072

# Increase TCP/UDP backlog
sudo sysctl -w net.core.somaxconn=1024
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=2048

# UDP buffer optimization
sudo sysctl -w net.core.netdev_max_backlog=5000

# TCP optimization
sudo sysctl -w net.ipv4.tcp_fin_timeout=30
sudo sysctl -w net.ipv4.tcp_tw_reuse=1
sudo sysctl -w net.ipv4.tcp_keepalive_time=600

# Disable source packet routing (security)
sudo sysctl -w net.ipv4.conf.all.send_redirects=0
sudo sysctl -w net.ipv4.conf.default.send_redirects=0

# Enable fast open (if supported)
sudo sysctl -w net.ipv4.tcp_fastopen=3

# Make permanent
sudo sysctl -p

Write to config file:

sudo tee -a /etc/sysctl.d/99-gameserver.conf > /dev/null <<'EOF'
# Game Server Network Optimization

# Socket buffer sizes (128 MB)
net.core.rmem_max=134217728
net.core.wmem_max=134217728
net.core.rmem_default=131072
net.core.wmem_default=131072

# Connection backlog
net.core.somaxconn=1024
net.ipv4.tcp_max_syn_backlog=2048
net.core.netdev_max_backlog=5000

# TCP optimizations
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_keepalive_time=600

# UDP optimization
net.ipv4.udp_rmem_min=8192
net.ipv4.udp_wmem_min=8192

# Fast open
net.ipv4.tcp_fastopen=3
EOF

sudo sysctl -p /etc/sysctl.d/99-gameserver.conf

Network Monitoring

Monitor network performance:

# Real-time network statistics
nethogs -t        # Top network consumers
iftop -i eth0     # Interface bandwidth usage
ss -s             # Summary statistics
netstat -s        # Detailed protocol statistics

# Per-connection monitoring
watch -n 1 'ss -u state ESTAB | wc -l'

# Packet loss monitoring
ping -c 100 google.com | grep "packet loss"

# Network errors
watch -n 1 'cat /proc/net/dev | grep eth0'

# Connection tracking
conntrack -C          # Active connections
conntrack -L | wc -l  # Total connections

# UDP port performance
sudo ss -ulnp | grep LISTEN

Network bandwidth limiting (rate limiting):

# Limit bandwidth to 100 Mbps on eth0
sudo tc qdisc add dev eth0 root tbf rate 100mbit burst 32kbit latency 400ms

# Show current qdisc
sudo tc qdisc show dev eth0

# Remove bandwidth limit
sudo tc qdisc del dev eth0 root

Disk I/O Optimization

Disk Performance Tuning

Monitor I/O performance:

# Real-time I/O statistics
iostat -x 1

# Per-disk performance
watch -n 1 'iostat -x 1 | tail -5'

# Process-specific I/O
iotop -o

# Disk queue depth
iostat -x 1 | grep -E "queue-sz"

I/O scheduler optimization:

# Check current scheduler
cat /sys/block/sda/queue/scheduler

# Set to noop (best for SSD)
echo "noop" | sudo tee /sys/block/sda/queue/scheduler

# Set to deadline (good for HDD)
echo "deadline" | sudo tee /sys/block/sda/queue/scheduler

# Set to mq-deadline (modern Linux)
echo "mq-deadline" | sudo tee /sys/block/sda/queue/scheduler

# Make permanent via grub/rc.local

Optimize file system mount options:

# Edit /etc/fstab
/dev/sda1 /home ext4 defaults,noatime,nodiratime,discard 0 2

# noatime: Don't update access time (faster)
# nodiratime: Don't update directory access time
# discard: TRIM SSD immediately

Game-Specific Tuning

Tick Rate Optimization

Tick rate determines game update frequency:

# Valheim (default 0.02s per tick = 50 ticks/sec)
# No direct tuning, depends on world size and player count

# ARK (tickrate 0.033s = 30 ticks/sec)
# Modify in Game.ini: [/Script/ShooterGame.ShooterGameMode]
# TickRate=30

# CS2 (32, 64, 128 tick servers available)
# Set at server launch: +sv_tickrate 128

# Rust (default 30 ticks/sec)
# Cannot be changed at runtime

Memory Management

Game-specific memory settings:

# ARK Survival Evolved (often needs 20GB+)
# Reduce player count or server side character data

# Rust (allocate specific memory)
export UE_SERVER_MEMORY=16GB

# 7 Days to Die (optimize world size)
# Smaller worlds = lower memory usage

Monitoring and Profiling

Real-Time Performance Dashboard

Create comprehensive monitoring script:

sudo tee /home/steam/perf_dashboard.sh > /dev/null <<'EOF'
#!/bin/bash

clear
echo "========================================="
echo "   Game Server Performance Dashboard"
echo "========================================="
echo "Time: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""

# CPU Information
echo "=== CPU Performance ==="
echo "Cores: $(nproc)"
echo "Load Average: $(cat /proc/loadavg | awk '{print $1, $2, $3}')"
echo "CPU Usage:"
top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print "  Idle: " 100-$1 "%"}'
echo ""

# Memory Information
echo "=== Memory Performance ==="
free -h | grep Mem
echo ""

# Network Information
echo "=== Network Performance ==="
echo "Active Connections:"
ss -s | grep -E "ESTAB|UDP"
echo ""

# Disk Information
echo "=== Disk Performance ==="
df -h /home/steam | awk 'NR==2 {printf "  Used: %s / %s (%s)\n", $3, $2, $5}'
echo ""

# Game Server Process
echo "=== Game Server ==="
PID=$(pgrep -f "valheim_server\|RustDedicated\|7DaysToDie" | head -1)

if [ ! -z "$PID" ]; then
    PROC=$(ps -p $PID -o comm=)
    MEM=$(ps -p $PID -o rss= | awk '{print $1/1024 " MB"}')
    CPU=$(ps -p $PID -o %cpu=)
    THREADS=$(ps -p $PID -o nlwp=)
    
    echo "Process: $PROC (PID: $PID)"
    echo "Memory: $MEM"
    echo "CPU: $CPU%"
    echo "Threads: $THREADS"
else
    echo "No game server process found"
fi
echo ""

# Port Status
echo "=== Network Ports ==="
PORTS=$(ss -tulnp | grep LISTEN | wc -l)
echo "Listening Ports: $PORTS"
EOF

sudo chmod +x /home/steam/perf_dashboard.sh

Run dashboard:

watch -n 5 /home/steam/perf_dashboard.sh

Profiling Tools

Install profiling tools:

sudo apt-get install -y sysstat blktrace perf-tools

# CPU profiling
perf record -F 99 -p $PID -g -- sleep 30
perf report

# Memory profiling
valgrind --leak-check=full ./game_server

# I/O profiling
blktrace -d /dev/sda -o - | blkparse -i -

Capacity Planning

Calculate server capacity:

# Single player baseline
BASELINE_CPU=2    # CPU % per player
BASELINE_MEM=50   # MB per player
BASELINE_BW=10    # Kbps per player

# Available resources
TOTAL_CORES=8
TOTAL_MEM=32000   # MB
TOTAL_BW=1000000  # Kbps (1 Gbps)

# Calculate capacity
MAX_PLAYERS_CPU=$((TOTAL_CORES * 100 / BASELINE_CPU))
MAX_PLAYERS_MEM=$((TOTAL_MEM / BASELINE_MEM))
MAX_PLAYERS_BW=$((TOTAL_BW / BASELINE_BW))

echo "CPU capacity: $MAX_PLAYERS_CPU players"
echo "Memory capacity: $MAX_PLAYERS_MEM players"
echo "Bandwidth capacity: $MAX_PLAYERS_BW players"
echo "Safe capacity: $((MAX_PLAYERS_CPU < MAX_PLAYERS_MEM ? (MAX_PLAYERS_CPU < MAX_PLAYERS_BW ? MAX_PLAYERS_CPU : MAX_PLAYERS_BW) : (MAX_PLAYERS_MEM < MAX_PLAYERS_BW ? MAX_PLAYERS_MEM : MAX_PLAYERS_BW))) players"

Advanced Techniques

Kernel Tuning for High Performance

# Reduce context switching overhead
sudo sysctl -w kernel.sched_min_granularity_ns=10000000
sudo sysctl -w kernel.sched_wakeup_granularity_ns=15000000

# Increase max memory map areas
sudo sysctl -w vm.max_map_count=262144

# Network connection tracking
sudo sysctl -w net.netfilter.nf_conntrack_max=1000000

# Reduce overcommit
sudo sysctl -w vm.overcommit_memory=1

Real-Time Priority

For critical latency-sensitive servers:

# Set real-time priority (careful! can lock up system)
sudo chrt -f -p 50 $PID  # FIFO with priority 50

# Monitor real-time processes
ps -eo class,rtprio,comm

Conclusion

Game server optimization requires careful monitoring and tuning across all system layers. By implementing these techniques, you can significantly improve server capacity and player experience.

Key points:

  • Use CPU affinity for better cache locality
  • Optimize network parameters for your player count
  • Monitor all performance metrics continuously
  • Tune game-specific settings for your community
  • Plan capacity based on actual measurements
  • Keep detailed performance baselines
  • Test changes in staging before production

Proper optimization can deliver 30-50% performance improvements and dramatically enhance player experience.