Files
for-servers/server/game-optimize.sh
T

204 lines
7.4 KiB
Bash
Executable File

#!/bin/bash
# game-optimize.sh — оптимизация Debian 12 под игровые серверы / игровой ПК
# Минимальный пинг, низкий bufferbloat, быстрые прерывания
# Запуск: curl -fsSL https://gitea.creative-tg1.ru/CREATIVE_tg1/for-servers/raw/branch/main/server/game-optimize.sh | sudo bash
set -e
LIMIT_NOFILE=65535
echo "============================================"
echo " Game Server Optimization — Debian 12"
echo "============================================"
echo ""
# ── 1. Сеть (sysctl) ─────────────────────────────────────
echo "[1/5] Сетевые оптимизации (sysctl)..."
cat >/etc/sysctl.d/99-game-network.conf <<SYSEOF
#################################################
# Queueing + Congestion Control
# cake активнее борется с bufferbloat, BBR для TCP
#################################################
net.core.default_qdisc = cake
net.ipv4.tcp_congestion_control = bbr
#################################################
# Socket buffers — маленькие, без bufferbloat
#################################################
net.core.rmem_default = 212992
net.core.wmem_default = 212992
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
#################################################
# Network backlog — умеренный
#################################################
net.core.netdev_max_backlog = 5000
net.core.somaxconn = 4096
#################################################
# TCP buffers — сбалансированные
#################################################
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
#################################################
# UDP buffers — для игрового трафика
#################################################
net.ipv4.udp_rmem_min = 16384
net.ipv4.udp_wmem_min = 16384
#################################################
# busy_poll — не ждём прерываний, опрашиваем
# ценой CPU (50 мкс), снижает latency на 20-50%
#################################################
net.core.busy_poll = 50
net.core.busy_read = 50
#################################################
# TCP low latency
#################################################
net.ipv4.tcp_low_latency = 1
net.ipv4.tcp_notsent_lowat = 16384
#################################################
# Security / routing
#################################################
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
#################################################
# Keepalive — быстрее обнаруживать разрыв
#################################################
net.ipv4.tcp_keepalive_time = 120
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
#################################################
# Ephemeral ports
#################################################
net.ipv4.ip_local_port_range = 1024 65535
#################################################
# TCP fastopen — только клиент
#################################################
net.ipv4.tcp_fastopen = 1
#################################################
# FIN timeout — быстрее освобождать сокеты
#################################################
net.ipv4.tcp_fin_timeout = 10
#################################################
# SYN backlog + retries — меньше ретраев, быстрее фейл
#################################################
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
SYSEOF
sysctl --system >/dev/null 2>&1
echo " OK"
# ── 2. NIC — txqueuelen + coalescing ─────────────────────
echo "[2/5] Сетевые интерфейсы (NIC)..."
for iface in $(ls /sys/class/net/ | grep -v lo); do
# Короткая очередь на интерфейсе
ip link set dev "$iface" txqueuelen 1000 2>/dev/null || true
# Выключаем coalescing прерываний (rx-usecs=0) — главный буст для пинга
ethtool -C "$iface" rx-usecs 0 2>/dev/null || true
ethtool -C "$iface" tx-usecs 0 2>/dev/null || true
# Увеличиваем кольцевой буфер NIC (если поддерживается)
ethtool -G "$iface" rx 4096 2>/dev/null || true
ethtool -G "$iface" tx 4096 2>/dev/null || true
echo " $iface OK"
done
# ── 3. ulimit ────────────────────────────────────────────
echo "[3/5] Лимиты файловых дескрипторов (limits.d)..."
cat >/etc/security/limits.d/90-nofile.conf <<LIMEOF
* soft nofile ${LIMIT_NOFILE}
* hard nofile ${LIMIT_NOFILE}
root soft nofile ${LIMIT_NOFILE}
root hard nofile ${LIMIT_NOFILE}
LIMEOF
echo " OK"
# ── 4. systemd DefaultLimitNOFILE ────────────────────────
echo "[4/5] Лимиты systemd (DefaultLimitNOFILE)..."
for conf in /etc/systemd/system.conf /etc/systemd/user.conf; do
if grep -q "^#DefaultLimitNOFILE=" "$conf" 2>/dev/null; then
sed -i "s/^#DefaultLimitNOFILE=.*/DefaultLimitNOFILE=${LIMIT_NOFILE}/" "$conf"
elif ! grep -q "^DefaultLimitNOFILE=" "$conf" 2>/dev/null; then
echo "DefaultLimitNOFILE=${LIMIT_NOFILE}" >> "$conf"
else
sed -i "s/^DefaultLimitNOFILE=.*/DefaultLimitNOFILE=${LIMIT_NOFILE}/" "$conf"
fi
done
systemctl daemon-reload
echo " OK"
# ── 5. IRQ affinity (если CPU > 1 ядро) ─────────────────
echo "[5/5] IRQ affinity..."
CPU_COUNT=$(nproc)
if [ "$CPU_COUNT" -gt 1 ]; then
# Распределяем сетевые прерывания по ядрам
for iface in $(ls /sys/class/net/ | grep -v lo); do
irqs=$(grep "$iface" /proc/interrupts 2>/dev/null | awk -F: '{print $1}' || true)
core=0
for irq in $irqs; do
irq_num="${irq//[^0-9]/}"
[ -z "$irq_num" ] && continue
if [ -f "/proc/irq/$irq_num/smp_affinity_list" ]; then
echo "$core" > "/proc/irq/$irq_num/smp_affinity_list" 2>/dev/null || true
core=$(( (core + 1) % CPU_COUNT ))
fi
done
done
echo " Распределено по $CPU_COUNT ядрам"
else
echo " 1 ядро — пропущено"
fi
# ── Итоги ─────────────────────────────────────────────────
echo ""
echo "============================================"
echo " Итог"
echo "============================================"
echo ""
echo "Очередь:"
sysctl net.core.default_qdisc
echo "Контроль перегрузки:"
sysctl net.ipv4.tcp_congestion_control
echo "busy_poll:"
sysctl net.core.busy_poll
echo "Soft ulimit: $(ulimit -Sn)"
echo "Hard ulimit: $(ulimit -Hn)"
echo ""
echo "NIC:"
for iface in $(ls /sys/class/net/ | grep -v lo); do
echo " $iface: txqueuelen=$(cat /sys/class/net/$iface/tx_queue_len 2>/dev/null || echo '?')"
done
echo ""
echo "Готово."
echo "После перезагрузки сессии / машины — ulimit -n покажет ${LIMIT_NOFILE}"