package linuxmodules

import (
	"fmt"
	"rubric/utils"
)

var PerformanceModule = Module{
	Key:         "performance",
	Aliases:     []string{"perf", "swap", "tuned", "производительность"},
	Title:       "Производительность системы",
	Description: "Темы 49–52: виртуальная память, планировщик CPU, tuned, Stratis",
	Run:         showPerformance,
}

func showPerformance() {
	utils.Header("Linux — Производительность системы")

	// ─── 49. Виртуальная память, swap ────────────────────────────
	utils.Section("49. Виртуальная память и swap")

	utils.Println("Виртуальная память — механизм ядра, позволяющий процессам иметь")
	utils.Println("больше памяти, чем физически установлено, за счёт использования диска.")
	fmt.Println()
	utils.Println(utils.ColorBold + "Swap — раздел/файл подкачки:" + utils.ColorReset)
	utils.Code(`Когда физической RAM не хватает, ядро перемещает
редко используемые страницы памяти на swap.
Это медленнее RAM в сотни раз, но лучше OOM-killer.

Типы swap:
- раздел swap (swap partition) — отдельный раздел диска
- файл swap (swapfile) — обычный файл на любой ФС`)

	utils.Println(utils.ColorBold + "Просмотр swap:" + utils.ColorReset)
	utils.Command("free -h", "RAM и swap (human-readable)")
	utils.Command("swapon --show", "активные swap-устройства")
	utils.Command("cat /proc/swaps", "то же через /proc")
	utils.Command("vmstat -s", "статистика памяти и swap")
	fmt.Println()
	utils.Println(utils.ColorBold + "Создание swapfile:" + utils.ColorReset)
	utils.Code(`# 1. Создать файл нужного размера:
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048  # 2 ГБ
# или быстрее:
sudo fallocate -l 2G /swapfile

# 2. Установить права (только root):
sudo chmod 600 /swapfile

# 3. Форматировать как swap:
sudo mkswap /swapfile

# 4. Активировать:
sudo swapon /swapfile

# 5. Добавить в /etc/fstab для автоматической активации:
echo '/swapfile none swap defaults 0 0' | sudo tee -a /etc/fstab`)

	utils.Println(utils.ColorBold + "Управление swap:" + utils.ColorReset)
	utils.Command("swapon /dev/sdb2", "активировать swap-раздел")
	utils.Command("swapoff /swapfile", "деактивировать")
	utils.Command("swapoff -a", "деактивировать все swap")
	utils.Command("swapon -a", "активировать все из /etc/fstab")
	fmt.Println()
	utils.Println(utils.ColorBold + "vm.swappiness — настройка агрессивности swap:" + utils.ColorReset)
	utils.Code(`# swappiness: 0–100
# 0   — использовать swap только при нехватке RAM
# 60  — по умолчанию
# 100 — активно перемещать страницы в swap

# Посмотреть:
cat /proc/sys/vm/swappiness
sysctl vm.swappiness

# Изменить временно:
sudo sysctl -w vm.swappiness=10

# Постоянно в /etc/sysctl.d/99-swap.conf:
vm.swappiness = 10
vm.vfs_cache_pressure = 50   # агрессивность освобождения кэша inode`)

	utils.Println(utils.ColorBold + "OOM-killer (Out Of Memory):" + utils.ColorReset)
	utils.Code(`Когда память (RAM + swap) исчерпана, ядро убивает процессы.

# Посмотреть OOM-события в логах:
dmesg | grep -i "oom\|killed process"
journalctl -k | grep -i oom

# oom_score — чем выше, тем вероятнее убийство:
cat /proc/PID/oom_score

# Защитить процесс от OOM (от -17 до 15):
echo -1000 > /proc/PID/oom_score_adj  # максимальная защита
# или через systemd в юните:
OOMScoreAdjust=-1000`)

	// ─── 50. Планировщик процессов ───────────────────────────────
	utils.Section("50. Планировщик процессов")

	utils.Println("Планировщик CPU распределяет процессорное время между процессами.")
	fmt.Println()
	utils.Println(utils.ColorBold + "Политики планирования:" + utils.ColorReset)
	utils.Code(`SCHED_OTHER   — обычные процессы (CFS — Completely Fair Scheduler)
SCHED_FIFO    — реального времени, без вытеснения
SCHED_RR      — реального времени, с квантованием
SCHED_BATCH   — фоновые задачи (CPU-bound)
SCHED_IDLE    — минимальный приоритет (ниже nice 19)
SCHED_DEADLINE — задачи с дедлайном`)

	utils.Println(utils.ColorBold + "nice и renice — управление приоритетом:" + utils.ColorReset)
	utils.Code(`# Nice: -20 (высший приоритет) → 19 (низший)
# По умолчанию: 0
# Только root может установить отрицательные значения

# Запустить с пониженным приоритетом:
nice -n 15 make -j8          # фоновая сборка

# Запустить с повышенным (root):
sudo nice -n -10 realtime_app

# Изменить приоритет запущенного процесса:
renice -n 5 -p 1234          # по PID
renice -n 10 -u alice        # всем процессам пользователя
sudo renice -n -5 -p 1234    # повысить (нужен root)`)

	utils.Println(utils.ColorBold + "chrt — управление политикой планирования:" + utils.ColorReset)
	utils.Command("chrt -p 1234", "показать политику процесса")
	utils.Command("chrt -f -p 50 1234", "установить FIFO с приоритетом 50")
	utils.Command("chrt -r 1234", "установить Round-Robin")
	utils.Command("chrt -o -p 0 1234", "обычная политика (SCHED_OTHER)")
	utils.Command("chrt -f 50 ./myapp", "запустить с FIFO приоритетом 50")
	fmt.Println()
	utils.Println(utils.ColorBold + "Просмотр загрузки CPU:" + utils.ColorReset)
	utils.Command("mpstat 1 5", "загрузка каждого CPU (пакет sysstat)")
	utils.Command("mpstat -P ALL 1", "все ядра каждую секунду")
	utils.Command("iostat -x 1", "статистика I/O дисков")
	utils.Command("sar -u 1 10", "средняя загрузка CPU 10 раз по 1 сек")
	utils.Command("perf top", "top по использованию CPU (нужен perf)")
	utils.Code(`# cpupower — управление частотой CPU:
cpupower frequency-info        # текущий режим
cpupower frequency-set -g performance  # режим производительности
# governors: performance, powersave, ondemand, conservative`)

	// ─── 51. tuned ────────────────────────────────────────────────
	utils.Section("51. Оптимизация производительности — tuned")

	utils.Println("tuned — демон автоматической оптимизации системы по профилям.")
	utils.Println("Настраивает CPU, диски, сеть под конкретные сценарии использования.")
	fmt.Println()
	utils.Println(utils.ColorBold + "Управление tuned:" + utils.ColorReset)
	utils.Command("systemctl status tuned", "статус демона")
	utils.Command("tuned-adm active", "текущий профиль")
	utils.Command("tuned-adm list", "список доступных профилей")
	utils.Command("tuned-adm profile throughput-performance", "применить профиль")
	utils.Command("tuned-adm recommend", "рекомендованный профиль для этой системы")
	utils.Command("tuned-adm off", "отключить tuned")
	fmt.Println()
	utils.Println(utils.ColorBold + "Встроенные профили:" + utils.ColorReset)
	utils.Code(`balanced             — баланс производительности и энергопотребления
powersave            — минимальное энергопотребление
throughput-performance — максимальная пропускная способность (серверы)
latency-performance  — минимальная задержка (без энергосбережения)
network-latency      — минимальная сетевая задержка
network-throughput   — максимальная сетевая пропускная способность
virtual-guest        — оптимизация для виртуальных машин
virtual-host         — оптимизация для хоста виртуализации
oracle               — для Oracle DB
mssql                — для MS SQL Server
desktop              — для рабочих станций`)

	utils.Println(utils.ColorBold + "Создание собственного профиля:" + utils.ColorReset)
	utils.Code(`# Профили хранятся в /usr/lib/tuned/ (системные)
# и /etc/tuned/ (пользовательские)

# Создать профиль на основе существующего:
mkdir /etc/tuned/myprofile
cat > /etc/tuned/myprofile/tuned.conf << 'EOF'
[main]
summary=Мой профиль
include=throughput-performance

[cpu]
governor=performance
energy_perf_bias=performance

[disk]
readahead=>4096

[sysctl]
vm.swappiness=10
net.core.somaxconn=65535
EOF

tuned-adm profile myprofile`)

	// ─── 52. Stratis ──────────────────────────────────────────────
	utils.Section("52. Управление многоуровневым хранилищем — Stratis")

	utils.Println("Stratis — менеджер хранилища от Red Hat (RHEL 8+).")
	utils.Println("Упрощает создание пулов, снапшотов и тонкого выделения места.")
	utils.Println("Работает поверх LVM и XFS.")
	fmt.Println()
	utils.Code(`Архитектура Stratis:
Physical Device (/dev/sdb, /dev/sdc)
        ↓
    Pool (пул хранилища)
        ↓
  Filesystem (XFS файловая система)

Особенности:
- Тонкое выделение (thin provisioning)
- Снапшоты (моментальные снимки)
- Кэширование (SSD как кэш для HDD)
- Автоматическое управление XFS`)

	utils.Println(utils.ColorBold + "Установка и запуск:" + utils.ColorReset)
	utils.Code(`# RHEL/Fedora:
dnf install stratisd stratis-cli
systemctl enable --now stratisd`)

	utils.Println(utils.ColorBold + "Работа с пулами:" + utils.ColorReset)
	utils.Code(`# Создать пул:
stratis pool create mypool /dev/sdb
stratis pool create mypool /dev/sdb /dev/sdc  # из нескольких дисков

# Добавить диск в существующий пул:
stratis pool add-data mypool /dev/sdd

# Добавить кэш (SSD):
stratis pool add-cache mypool /dev/nvme0n1

# Список пулов:
stratis pool list

# Детали пула:
stratis pool info mypool`)

	utils.Println(utils.ColorBold + "Работа с файловыми системами:" + utils.ColorReset)
	utils.Code(`# Создать ФС в пуле:
stratis filesystem create mypool myfs

# Список ФС:
stratis filesystem list
stratis fs

# Монтирование:
mount /stratis/mypool/myfs /mnt/data

# В /etc/fstab (с x-systemd.requires):
/stratis/mypool/myfs  /mnt/data  xfs  defaults,x-systemd.requires=stratisd.service  0 0

# Создать снапшот:
stratis filesystem snapshot mypool myfs myfs-snapshot

# Удалить ФС:
stratis filesystem destroy mypool myfs

# Удалить пул (сначала удалить все ФС):
stratis pool destroy mypool`)

	utils.Note("Stratis автоматически форматирует дискипод XFS. Не используйте mkfs вручную.")
	utils.Note("Снапшоты — это отдельные ФС. Можно смонтировать для восстановления файлов.")

	utils.Footer()
}
