Устранение Page Cache Thrashing и OOM при круглосуточной записи
Одна из самых опасных проблем при круглосуточной записи видео в Linux — вымывание кеша страниц ядра (Page Cache Thrashing) и аварийные остановки OOM Killer.
1. Первопричина: почему память в Linux переполняется при записи видео
При записи видеопотоков через стандартный дисковый ввод-вывод (os.File.Write() в Go или write() в C) ядро Linux не пишет данные на диск мгновенно.
Вместо этого:
- Linux кеширует каждый записанный байт: Ядро помещает видеоблоки в Page Cache (RAM) со статусом "грязных страниц".
- Отложенный сброс: Фоновые потоки ядра (
pdflush/kswapd) сбрасывают страницы на диск пачками. - Кризис вытеснения кеша: Поток видео непрерывен. Ядро удерживает страницы в RAM, пока до 90%+ физической памяти не займет кеш.
- Авария OOM: Когда соседнему процессу (БД, WebRTC-энкодеру или GC Go) срочно требуется память, Linux вынужден останавливать I/O для освобождения страниц или вызывать OOM Killer, аварийно завершая видеосервер.
2. Архитектурное решение RUSEON Core: POSIX_FADV_DONTNEED
В RUSEON Core эта проблема решена на уровне системных вызовов ядра без небезопасных хаков ОС:
- Запись блоками fMP4: Видео сохраняется независимыми фрагментами.
- Явное вытеснение страниц: Сразу после завершения записи фрагмента RUSEON вызывает интерфейс
CacheDropper:
go
// 1. Запись части fMP4 на диск
_ = part.Marshal(file)
// 2. Указание ядру Linux немедленно вытеснить страницы из RAM
if dropper, ok := file.(registry.CacheDropper); ok {
_ = dropper.DropCache()
}Практические результаты:
- Отсутствие накопления кеша: Расход памяти остается строго плоским (~471 МБ RSS при 600 камерах) в течение сотен дней непрерывной работы.
- Предсказуемый ввод-вывод: Устраняются всплески I/O Wait и зависания системы.
- Работа без root-прав: Решение стабильно функционирует в Docker-контейнерах и Kubernetes-подах без привилегированного режима.