Jump to content
View in the app

A better way to browse. Learn more.

T.M.I IThub

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Сервер работает, но медленно. Страницы грузятся с задержкой, база данных тормозит, под нагрузкой всё падает. Прежде чем покупать новое железо или мигрировать на более дорогой тариф — убедитесь, что вы используете текущее на 100%. Эта статья о том, как профилировать, диагностировать и оптимизировать Linux-сервер под реальную нагрузку.


Методология: сначала измеряем, потом меняем

Главная ошибка при оптимизации — начинать с изменений без понимания проблемы. «Давайте увеличим swap» или «добавим RAM» — это стрельба вслепую. Правильный подход: измерить → найти узкое место → устранить → снова измерить.

Инструментарий делится на уровни детализации:

системный уровень   → top, htop, vmstat, iostat, sar
процессный уровень  → perf, strace, ltrace, lsof
сетевой уровень     → ss, netstat, iftop, nethogs, tcpdump
дисковый уровень    → iotop, blktrace, fio
профилировщики      → perf, bpftrace, flame graphs

CPU: диагностика и оптимизация

Что жрёт процессор

# Базовый top с сортировкой по CPU
top -o %CPU

# htop — интерактивный, красивый
htop

# Детальная картина по ядрам
mpstat -P ALL 1 5  # 5 измерений каждую секунду

# pidstat — статистика по процессам
pidstat -u 1 10   # каждую секунду, 10 раз

Смотрите на us (userspace), sy (kernel), wa (iowait), st (steal — для виртуалок). Высокий wa — проблема с диском или сетью, а не с CPU.

Приоритеты процессов — nice и ionice

# Запустить процесс с низким приоритетом
nice -n 19 ./heavy_backup.sh

# Изменить приоритет запущенного процесса
renice -n 10 -p 1234

# Приоритет I/O (для компилятора в фоне)
ionice -c 3 -p 1234   # класс idle — работает только когда диск свободен

# Совместно
ionice -c 2 -n 7 nice -n 19 make -j$(nproc)

Привязка процессов к ядрам — CPU affinity

Для highload-сервисов критично избегать перепрыгивания между ядрами (cache miss):

# Запустить nginx worker на ядрах 0-3
taskset -c 0-3 nginx

# Изменить для запущенного процесса
taskset -pc 0-3 $(pgrep nginx | head -1)

# Посмотреть текущую привязку
taskset -p 1234

perf — профилировщик ядра

# Установка
apt install linux-tools-generic linux-tools-$(uname -r)

# Общая статистика производительности
perf stat ./your_program

# Найти горячие функции (10 секунд)
perf top -p $(pgrep php-fpm | head -1)

# Запись для flame graph
perf record -F 99 -g -p $(pgrep nginx) -- sleep 10
perf script > perf.out

# Flame graph (нужен Brendan Gregg's flamegraph)
git clone https://github.com/brendangregg/FlameGraph
./FlameGraph/stackcollapse-perf.pl perf.out | ./FlameGraph/flamegraph.pl > flame.svg

Flame graph — это визуализация стека вызовов. Широкие «языки пламени» = много времени в этой функции.


Память: диагностика и управление

Понимаем использование памяти

# Читаем правильно — free показывает не совсем то, что думаем
free -h
# "available" — реально доступная память, не "free"

# Детальная информация
cat /proc/meminfo

# Кто сколько жрёт
ps aux --sort=-%mem | head -20

# Smem — более точные данные (учитывает shared memory)
apt install smem
smem -tk -s uss | tail -5

Virtual Memory: tuning через sysctl

/etc/sysctl.d/99-vm.conf:

# vm.swappiness — насколько агрессивно использовать swap
# 0 = почти не свопировать (но не отключить совсем)
# 10 = для серверов с достаточной RAM — хорошее значение
# 60 = дефолт, нормально для десктопа
vm.swappiness = 10

# vm.dirty_ratio — процент RAM, при котором начинается синхронный flush на диск
# Для серверов с SSD можно увеличить
vm.dirty_ratio = 20
vm.dirty_background_ratio = 5

# Размер таблицы vnodes
vm.vfs_cache_pressure = 50  # меньше = кешируем дольше

# Отключаем OOM killer для критичных процессов
# vm.overcommit_memory = 2  # осторожно, лучше знать что делаете

Huge Pages для баз данных

PostgreSQL, MySQL и Java-приложения хорошо работают с huge pages (2MB вместо 4KB):

# Проверяем текущее состояние
grep -i huge /proc/meminfo

# Transparent Huge Pages (THP) — автоматически
cat /sys/kernel/mm/transparent_hugepage/enabled
# Для баз данных THP лучше отключить!
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# Статические huge pages для PostgreSQL
# В /etc/sysctl.conf:
# vm.nr_hugepages = 1024  # 1024 * 2MB = 2GB

# В PostgreSQL
# huge_pages = on  # в postgresql.conf

Диски: I/O оптимизация

Диагностика дисковой подсистемы

# Общая нагрузка на диски в реальном времени
iostat -xz 1

# Ключевые метрики:
# %util — насколько занят диск (>80% = проблема)
# await — среднее время ожидания запроса (мс)
# r/s, w/s — операции чтения/записи в секунду

# Кто именно читает/пишет
iotop -o  # только активные процессы

# Детальная трассировка
blktrace -d /dev/sda -o - | blkparse -i -

Планировщик I/O

# Посмотреть текущий scheduler
cat /sys/block/sda/queue/scheduler

# Выбор scheduler:
# none/mq-deadline — для NVMe SSD (hardware очередь хороша)
# mq-deadline — для SATA SSD и HDD
# bfq — для десктопа, справедливое распределение

echo mq-deadline > /sys/block/sda/queue/scheduler

# Закрепить через udev /etc/udev/rules.d/60-scheduler.rules:
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", \
  ATTR{queue/scheduler}="none"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", \
  ATTR{queue/scheduler}="mq-deadline"

Параметры очереди

# Размер очереди запросов (для NVMe можно больше)
cat /sys/block/nvme0n1/queue/nr_requests
echo 1024 > /sys/block/nvme0n1/queue/nr_requests

# Read-ahead: сколько данных читать заранее
# Для баз данных — уменьшаем, для стриминга файлов — увеличиваем
blockdev --setra 256 /dev/sda  # 256 * 512 = 128KB

Тестирование производительности дисков

# fio — промышленный стандарт для тестирования I/O
apt install fio

# Тест случайного чтения 4K (как у базы данных)
fio --name=randread --ioengine=libaio --iodepth=32 \
    --rw=randread --bs=4k --direct=1 --size=1G \
    --numjobs=4 --runtime=60 --group_reporting

# Последовательная запись (как у лога)
fio --name=seqwrite --ioengine=libaio --iodepth=8 \
    --rw=write --bs=1M --direct=1 --size=10G \
    --numjobs=1 --runtime=60 --group_reporting

Сеть: тюнинг стека TCP/IP

Диагностика сетевой подсистемы

# Текущие соединения и их состояния
ss -s  # краткая статистика
ss -tnp  # все TCP соединения с процессами

# Ширина полосы в реальном времени
iftop -i eth0
nethogs eth0  # по процессам

# Статистика сетевого интерфейса
ip -s link show eth0

# Ошибки и дропы
ethtool -S eth0 | grep -i drop
cat /proc/net/dev

Тюнинг TCP стека

/etc/sysctl.d/99-network.conf:

# Размеры буферов сокетов
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.core.rmem_default = 65536
net.core.wmem_default = 65536

# TCP буферы (min, default, max в байтах)
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728

# BBR — современный алгоритм контроля перегрузки Google
# Значительно улучшает пропускную способность при потерях
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

# TIME_WAIT sockets
net.ipv4.tcp_tw_reuse = 1      # переиспользуем TIME_WAIT сокеты для новых соединений
net.ipv4.tcp_fin_timeout = 15  # уменьшаем время ожидания FIN

# Очередь соединений
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# Keep-alive для обнаружения мёртвых соединений
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5

# Диапазон портов для исходящих соединений
net.ipv4.ip_local_port_range = 1024 65535
# Проверяем что BBR загружен
sysctl net.ipv4.tcp_congestion_control
lsmod | grep bbr

Настройка сетевого интерфейса

# Проверяем настройки карты
ethtool eth0

# Включаем offloading (перекладываем работу на NIC)
ethtool -K eth0 tso on gso on gro on  # TCP/Generic segmentation offload

# Ring buffers — увеличиваем для highload
ethtool -G eth0 rx 4096 tx 4096

# IRQ affinity — привязываем прерывания к ядрам
cat /proc/interrupts | grep eth0
# Пишем скрипт привязки через /proc/irq/N/smp_affinity

Профилирование с bpftrace и eBPF

Современный инструментарий для глубокого анализа без влияния на производительность:

# Установка
apt install bpftrace

# Топ системных вызовов
bpftrace -e 'tracepoint:syscalls:sys_enter_* { @[probe] = count(); }'

# Медленные запросы к диску (>10мс)
bpftrace -e 'tracepoint:block:block_rq_complete { 
    if (args->nr_sector > 0) {
        $latency = (nsecs - @start[args->sector]) / 1000000;
        if ($latency > 10) { printf("Slow I/O: %d ms\n", $latency); }
    }
}'

# Трассировка TCP retransmits
bpftrace -e 'tracepoint:tcp:tcp_retransmit_skb { @[comm] = count(); }'

Профилирование PHP-FPM специфически

Раз уж мы работаем с PHP:

# Статус PHP-FPM (если включён status page)
curl http://localhost/fpm-status?full

# Медленные запросы через slow log
# В php-fpm pool config:
# slowlog = /var/log/php-fpm/slow.log
# request_slowlog_timeout = 5s

# Анализ slow log
sort -t$'\t' -k1 -rn /var/log/php-fpm/slow.log | head -20

# strace на php-fpm worker
strace -c -p $(pgrep php-fpm | head -1) 2>&1 | head -50

Система мониторинга производительности

sar — System Activity Reporter

apt install sysstat
systemctl enable sysstat

# Статистика за сегодня
sar -u  # CPU
sar -r  # память
sar -b  # I/O
sar -n DEV  # сеть

# За конкретное время
sar -u -s 10:00:00 -e 11:00:00

# Сохранить историю в файл
sar -A > /tmp/system_report_$(date +%Y%m%d).txt

vmstat — обзор системы одной командой

# Запускаем каждую секунду
vmstat 1

# Колонки:
# procs: r(run queue), b(blocked)
# memory: swpd, free, buff, cache
# io: bi(blocks in), bo(blocks out)
# cpu: us, sy, id, wa, st

Если r > числа CPU — CPU перегружен. Если wa > 20% — проблема с диском.


Тюнинг NUMA-систем

Для серверов с несколькими CPU-сокетами:

# Проверяем топологию NUMA
numactl --hardware
numastat

# Запуск на конкретном NUMA узле
numactl --cpunodebind=0 --membind=0 ./your_app

# Для Redis на NUMA-системе
numactl --interleave=all redis-server

# Автоматический балансировщик NUMA
echo 1 > /proc/sys/kernel/numa_balancing

Чеклист оптимизации

Порядок важен — сначала находим, потом чиним:

  1. Измерить базовые метрики (top, iostat, free, ss)

  2. Определить узкое место (CPU / RAM / Disk I/O / Network)

  3. Детальное профилирование проблемной подсистемы

  4. Применить изменение

  5. Снова измерить — убедиться в улучшении

  6. Применить к продакшну через конфиги (sysctl, udev, systemd)

Помните: преждевременная оптимизация — корень всех зол. Оптимизируйте то, что реально тормозит, с данными в руках.

User Feedback

Create an account or sign in to leave a review

There are no reviews to display.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.