Аннотация

Лимит памяти отвечает на вопрос «где остановить рост», но не на вопрос «останется ли отзывчивым соседний сервис». В cgroup v2 memory.high замедляет процессы и заставляет их участвовать в reclaim, memory.max задаёт последнюю границу с возможным cgroup OOM, а memory.low защищает часть использования от конкурирующего reclaim. PSI показывает потерю времени из-за нехватки ресурса, а не количество свободных байтов. Поэтому бюджет одного VPS должен связывать объём, иерархию, допустимую деградацию и действие при длительном давлении.123

Данные на 2026-11-12. Допущение автономного обзора: один Linux VPS, единая иерархия cgroup v2, foreground API и БД рядом с прерываемыми фоновыми заданиями. Для проверяемой семантики выбраны Linux v6.12 и systemd v257, а не заявленная последняя версия: ссылки ведут на документы этих тегов. Docker Docs и README Senpai рассматриваются как снимки, прочитанные сегодня; отдельный arXiv-препринт — как ограниченное внешнее исследование. Живой хост не обследовался, лимиты не менялись, pressure-test и бенчмарки не выполнялись. Конфигурация и план испытания ниже — предложения, не проверенный deployment.

Основной вывод: начать стоит с отдельной ветви для прерываемой работы, измеренного рабочего набора важных сервисов и наблюдения PSI вместе с latency. memory.high полезен, только если замедление приводит к уменьшению работы или другой реакции оператора; сам по себе он способен оставить сервис в долгом reclaim. memory.max ограничивает область ущерба, но не создаёт резерв ОС и не гарантирует завершение транзакций.134

Введение

В обзоре локального инференса память обсуждалась как ограничение модели и KV-cache. В статье о self-hosted поиске — как стоимость индекса, mmap и импорта. В сравнении NixOS, Ansible и Compose — как часть конфигурации инфраструктуры. Здесь другой вопрос: кто уступает ресурс, когда все эти приложения работают одновременно, и что считать приемлемым отказом.

Цель — связать контроллер памяти с эксплуатационным контрактом: foreground сохраняет полезную отзывчивость, background уступает или прекращается, а аварийная граница не превращается в основной механизм планирования. Это инженерный вывод из различия между защитой, throttling и hard limit, а не обещание конкретного p99.123

Границы. Не сравниваются Kubernetes, NUMA-политики, GPU VRAM и настройки hypervisor. Описанный бюджет относится к памяти Linux-гостя и обычному memory controller; это не общий предел всей памяти оборудования. Для HugeTLB документация v6.12 отдельно оговаривает opt-in учёт и необходимость управления заранее выделенным пулом другими средствами. Нельзя переносить пример на такой workload без дополнительного расчёта.1

1. Считать нужно потребление группы, а не сумму колонок RSS

memory.current — текущее использование cgroup вместе с потомками. memory.stat раскрывает его состав: anon — анонимные отображения, file — filesystem cache, включая tmpfs и shared memory, kernel — учитываемая память ядра. Это не перечень независимых строк, которые разрешено бездумно сложить: например, shmem и file_mapped описывают стороны уже учтённых файловых страниц, а kernel_stack входит в более общий учёт kernel memory.1

RSS и PSS отвечают на другой вопрос. /proc/PID/smaps описывает резидентные страницы отображений процесса; PSS распределяет разделяемую страницу между использующими её процессами. Эти показатели помогают понять приложение, но не заменяют cgroup accounting. Особенно ошибочно прибавлять полный RSS mmap-индекса к тем же страницам page cache как к отдельному расходу: получится двойной счёт одного содержимого.51

Есть и временная граница учёта. Linux начисляет память группе, которая её создала, и перенос процесса в другую cgroup не переносит автоматически ранее начисленные страницы. Разделяемая память не раскладывается между группами по правилу PSS. Поэтому измерение задания, сначала запущенного в общей session, а потом перемещённого в отдельную ветвь, может не описывать тот бюджет, который предполагал экспериментатор. Запускать исследуемую работу сразу в нужной группе — рекомендация, вытекающая из этой семантики.1

На уровне хоста MemAvailable полезнее наивного «свободно»: это оценка памяти для новых приложений без swap, учитывающая watermarks и то, что не весь cache/slab можно освободить. Но и она не является обещанным резервом конкретному сервису. Для бюджета нужны одновременно системная оценка, состав использования групп и цена вытеснения их страниц.52

2. Четыре границы, четыре разных последствия

Защита: low не выдаёт память заранее

memory.low — best-effort защита уже используемой памяти в пределах эффективной границы. Ядро старается не reclaim её, пока в незащищённых группах остаётся подходящая память. Если её больше нет, защищённые страницы тоже становятся кандидатами. Это не preallocation, не запрет роста соседей и не гарантия, что приложение никогда не получит OOM.1

memory.min сильнее: в эффективных пределах reclaim не допускается; когда доступной незащищённой памяти не остаётся, возможен OOM. Документация прямо предупреждает, что чрезмерная защита может привести к постоянным OOM. Для небольшого shared VPS осторожный low обычно разумнее, чем объявление всех важных сервисов неприкосновенными через min; это рекомендация по риску, не универсальное правило ядра.1

High: механизм замедления, а не мягкое название max

Определение Linux v6.12 стоит прочитать буквально:

“Going over the high limit never invokes the OOM killer and under extreme conditions the limit may be breached.”1

При превышении memory.high процессы замедляются и попадают под сильное reclaim pressure. Смысл не в гарантии «никогда не больше этого числа», а в изменении цены дальнейшего потребления. Растущий memory.events:high может означать, что контроллер делает именно ожидаемую работу. Если одновременно растут задержки запросов и нет реакции на давление, это уже не успешное распределение ресурса, а затянувшаяся деградация.12

Max: аварийная граница внутри ограниченной области

Когда использование достигает memory.max и уменьшить его нельзя, OOM killer вызывается внутри cgroup. Однако документация допускает временное превышение и отдельно описывает классы allocations, которые не вызывают OOM killer: возможен возврат -ENOMEM или другой исход. Формула «ровно на лимите немедленно убьют крупнейший процесс» неверна даже как описание интерфейса.1

systemd v257 рекомендует MemoryHigh= как основной механизм управления, а MemoryMax= как последнюю линию защиты. Это разные роли: high должен сделать дальнейшую работу достаточно дорогой, чтобы появилась обратная связь, max — ограничить разрушительный рост. Между ними нужен запас для переходных состояний; его размер нельзя вывести из универсального процента RAM без workload.3

3. Иерархия важнее красивых лимитов на листьях

Потомок не может отменить ограничение предка. systemd сообщает EffectiveMemoryMax= с учётом наиболее строгого ограничения юнита и родительских slices. Если два сервиса имеют большие индивидуальные caps, но общий родитель уже исчерпал бюджет, отказ определяется общей ветвью. Проверять только файл memory.max процесса недостаточно: нужно пройти путь до корня и увидеть конкурентов под каждым ограниченным предком.31

Защита тоже проходит по иерархии. Для MemoryLow= и MemoryMin= systemd v257 обычно требует соответствующего распределения у всех предков, кроме корневого slice. При превышении суммарных запросов защиты доступная защита делится с учётом фактического использования ниже границ. У Linux есть отдельный mount option memory_recursiveprot; его существование — ещё одна причина не считать унаследованную защиту одинаковой на любом хосте.31

Предлагаемая структура проста: workload.slice объединяет приложения, workload-front.slice — latency-sensitive API/БД, workload-batch.slice — индексирование, backup preparation и сборки. В systemd дефис обозначает иерархию: workload-front.slice находится в workload.slice. Такая структура разделяет классы допустимого отказа, а не просто красивые имена процессов.6

Для зависимых компонентов границу надо выбирать по целостности workload. memory.oom.group=1 позволяет рассматривать группу как неделимую и убивать её процессы вместе; исключение — процессы с oom_score_adj=-1000. Это полезно против полумёртвого pipeline, но не делает запись данных атомарной. В systemd v257 OOMPolicy=kill устанавливает соответствующий атрибут; stop означает чистую остановку оставшейся части юнита менеджером, а continue оставляет его работать.17

4. Бюджет — гипотеза, которую можно опровергнуть

Для вымышленного VPS с 8 GiB рассматриваем следующий стартовый проект. Это арифметический пример автора, не sizing guide и не результаты измерений:

  • 2 GiB — целевой запас вне ветви приложений: ОС, инфраструктура и аварийный резерв;
  • 6 GiB — MemoryMax родителя workload.slice, при MemoryHigh=5G;
  • foreground: MemoryLow=2G, MemoryHigh=3G, MemoryMax=4G;
  • background: MemoryHigh=1536M, MemoryMax=2G, без гарантированной защиты.

Сумма leaf max здесь равна общему max, но это сознательно консервативная конструкция примера, не требование cgroup. Главное ограничение бюджета: cap в 6 GiB не резервирует оставшиеся 2 GiB для ОС. Другие ветви тоже способны расти, а reclaimable cache не является бесплатной памятью без последствий. Следовательно, корректность проекта ещё надо проверить при одновременных пиках и по всей иерархии.153

Ниже только иллюстрация формата unit-файлов; команды установки и активации намеренно не приведены. Значения выбраны из вымышленного бюджета. В systemd суффиксы M и G для этих параметров имеют основание 1024.36

# workload.slice
[Slice]
MemoryAccounting=yes
MemoryLow=2G
MemoryHigh=5G
MemoryMax=6G

# workload-front.slice
[Slice]
MemoryLow=2G
MemoryHigh=3G
MemoryMax=4G

# workload-batch.slice
[Slice]
MemoryHigh=1536M
MemoryMax=2G

Один slice ничего не классифицирует автоматически. Нативный сервис должен быть помещён в нужную ветвь через Slice=, а разовое задание можно запускать через systemd-run --slice=workload-batch.slice с нужными properties. Важен не только процесс-родитель, но все участвующие worker-процессы. Руководство systemd-run различает transient service и scope; пример нельзя считать готовым рецептом без выбора их жизненного цикла.38

5. Swap, overcommit и zram не заменяют бюджет

В cgroup v2 memory.swap.max — отдельный предел swap usage; это не сумма RAM и swap. При достижении границы анонимная память группы больше не может выгружаться в swap. Настройка MemorySwapMax= systemd управляет этим же атрибутом. Запрет swap может убрать один путь освобождения RAM, поэтому его нельзя автоматически объявить способом защитить latency.13

Глобальный vm.swappiness в Linux v6.12 описывает относительную стоимость swap I/O и filesystem paging, а не «процент RAM, после которого включится swap». В документации диапазон до 200 и отдельно допускаются значения выше 100 для подходящих in-memory swap конфигураций. Здесь важно не выбрать новое магическое число, а отказаться от неверной модели параметра; оптимум руководство прямо называет workload-dependent.9

vm.overcommit_memory управляет другим слоем: допуском обязательств виртуальной памяти. Режим 2 ограничивает общий commit относительно swap и заданной доли/объёма физической памяти. Это не резерв рабочего набора конкретной cgroup и не замена её hard limit. Приложение может столкнуться с отказом allocations раньше физического исчерпания; изменение глобальной политики требует отдельной проверки поведения приложения.101

zram хранит сжатые данные в RAM. Его disksize задаёт логическую ёмкость устройства, mem_limit — предел памяти для хранения; статистика mem_used_total включает allocator fragmentation и metadata overhead. Поэтому «добавили swap на zram» не означает «создали столько же новой физической памяти». Сжимаемость и стоимость обработки нужно наблюдать, а не предполагать по размеру устройства.11

Практическая рекомендация — определить swap policy отдельно для классов нагрузки и записывать её в протокол испытания. Без этого одинаковые MemoryHigh/Max могут проверяться с разным пространством для вытеснения, а «улучшение» окажется сменой сценария. Документация systemd-oomd дополнительно предупреждает: swap даёт userspace-реакции время, без него давление может расти значительно резче.41

6. PSI измеряет остановленное время, не занятые гигабайты

Определение full в первичном документе:

“The “full” line indicates the share of time in which all non-idle tasks are stalled on a given resource simultaneously.”2

some учитывает интервалы, когда на ресурсе задерживается хотя бы часть задач; full — когда одновременно остановлены все non-idle задачи рассматриваемого набора. avg10, avg60, avg300 выражают доли времени в процентах, а total — накопленное stall time в микросекундах. Это не доля использованной RAM, не сумма задержек каждого HTTP-запроса и не идентификатор виновного соседа.2

Для собственного окна наблюдения можно брать прирост total и делить на длительность окна в тех же единицах. Например, условные, не измеренные 150000 μs за 5 секунд дают 3% stall time соответствующего состояния. Сравнивать нужно один и тот же счётчик, учитывая пересоздание cgroup и разрывы наблюдения. full — не добавка к some: это более узкое состояние, а не независимый вид расхода.2

Нужны оба масштаба: /proc/pressure/memory для системы и memory.pressure для конкретной группы. Низкий host PSI не оправдывает высокий PSI foreground-группы; group-local high способен давить её даже при наличии RAM вне её бюджета. И наоборот, один пострадавший leaf не раскрывает причину конкуренции у общего предка. Диагноз строится по иерархии, событиям и составу памяти, а не по одному проценту.12

Минимальный наблюдательный набор: memory.current, memory.stat, memory.swap.current, memory.events, memory.events.local, group PSI, host PSI и latency/error rate самого foreground. events иерархичен, events.local показывает события этого уровня. high, max, oom и oom_kill — разные накопительные счётчики; max не означает, что процесс уже убит, а oom_kill учитывает процессы группы, убитые любым OOM killer.1

При растущем workingset_refault_file стоит проверить, не вытесняются ли страницы, которые сразу понадобятся снова; при росте pgscan без полезного прогресса — цену reclaim. Но это диагностические сигналы, не готовый causal verdict. Главный критерий принятия бюджета — обслуживание запросов и восстановление после снятия давления, а не максимально маленький memory.current.12

7. Кто реагирует: приложение, планировщик заданий или oomd

У memory.high нет встроенного знания, что индексирование можно отложить. Простейшая политика автора: при устойчивом давлении сначала уменьшить concurrency background, затем не принимать новые задания, затем остановить безопасно прерываемую работу. Для каждой реакции заранее нужны условие, задержка, hysteresis и обратный переход. Это проект обратной связи, а не часть автоматического поведения memory controller.13

Приложение тоже может сотрудничать. В документации systemd v257 протокол $MEMORY_PRESSURE_WATCH / $MEMORY_PRESSURE_WRITE передаёт сервису файл для наблюдения и данные настройки; поддерживающий его код может освобождать caches или другие необязательные ресурсы. Само включение MemoryPressureWatch= не переписывает приложение и не гарантирует, что произвольный runtime уменьшит heap.12

systemd-oomd — другой уровень: он наблюдает давление и может послать SIGKILL всем процессам выбранной группы раньше kernel OOM. В v257 ManagedOOMMemoryPressure=kill включает наблюдение указанной группы, но кандидатами на уничтожение служат подходящие потомки. Сам наблюдаемый юнит не становится собственной жертвой; допустимы leaf cgroups и группы с memory.oom.group=1.43

Это меняет дизайн slices. Нельзя считать ManagedOOMMemoryPressure=auto на ребёнке иммунитетом, если предок включил политику kill. Нельзя и включить kill на широкой ветви, а затем считать её «мониторингом без последствий». В oomd.conf v257 pressure limit относится к доле времени за окно, а duration — к длительности превышения; ни один из них не обозначает процент занятой RAM.313

Операционная рекомендация: сначала проверить видимые oomctl группы и границы кандидатов, затем рассматривать kill policy только для ветви, которую действительно разрешено потерять. Это не graceful load shedding. Наличие restart policy не доказывает корректность восстановления приложения, и выбор удобной OOM-жертвы не заменяет проверяемой сохранности данных.47

8. Docker: конфигурация клиента ещё не доказательство enforcement

Docker Docs описывает --memory как memory limit, а положительный --memory-swap — как сумму memory и swap. Это отличается от memory.swap.max и MemorySwapMax. Равные положительные --memory и --memory-swap запрещают swap контейнеру; ноль для --memory-swap трактуется как unset. Переносить одинаковые числа между этими интерфейсами без перевода семантики нельзя.14

Compose даёт mem_limit, mem_reservation, memswap_limit и cgroup_parent; при одновременном использовании соответствующих полей Deploy Specification значения должны быть согласованы. Но название reservation не доказывает, что получен нужный memory.high: Docker описывает soft reservation как отдельный механизм при contention. Проверять надо фактические memory.low/high/max/swap.max в созданной иерархии и выбранный cgroup driver, а не сходство названий.1514

Для общего бюджета контейнеров предусмотрен --cgroup-parent; Compose также позволяет задать parent. Отсюда важный вывод: unit, который лишь запускает Docker CLI, не является достаточным доказательством, что контейнер оказался под его лимитами. Реальное дерево runtime нужно проверить отдельно. Системные slices из предыдущего раздела — схема полномочий над ресурсом, не готовая конфигурация конкретного Docker-хоста.1615

9. Как проверить проект, не устраивая OOM на production

Следующий протокол — предложение для отдельной тестовой VM, а не выполненное испытание. Сначала фиксируются версии kernel/systemd/runtime, RAM, swap/zram, cgroup topology и CPU/I/O ограничения. Затем выбирается foreground-canary с внешним генератором запросов и записываются latency, ошибки, throughput и время восстановления. Одни PSI counters не заменяют пользовательский outcome.24

Сравнивать следует одну и ту же foreground-нагрузку: без background, с background под одним hard cap, затем с high/защитой и явной реакцией на давление. Во всех вариантах сохраняются общий safety cap, входные данные, concurrency и swap policy; каждый новый вариант меняет оговорённый механизм. Важно проверять не только поступательный рост anonymous memory, но и cache-heavy чтение, импорт, cold start и совпавшие пики. Это предложенный дизайн, вытекающий из разных видов учитываемой памяти.15

До запуска задаются критерии остановки: нарушение latency/error budget foreground, потеря canary, опасное давление родителя, OOM важной ветви либо невозможность восстановить исходную конфигурацию. Не нужно специально доводить VM до global OOM ради демонстрации hard limit. После снятия нагрузки проверяются восстановление задержек, завершение заданий, целостность данных и отсутствие бесконечного restart cycle. Конкретные пороги принадлежат требованиям приложения, а не ядру.17

Результаты надо показывать по фазам: baseline, рост нагрузки, steady pressure, recovery. Для PSI берутся дельты counters, для приложения — одинаковые определения latency и ошибок; невыдавший ответ запрос не исчезает из отчёта. Это методологическая рекомендация: без неё «p99 улучшился» может означать лишь, что часть запросов перестала завершаться.

Наконец, не следует лечить эксперимент регулярным drop_caches: документация Linux предупреждает о CPU/I/O цене восстановления cache и не рекомендует это вне testing/debugging. Если cold-cache вариант нужен, он должен быть отдельным явно описанным сценарием, не скрытой частью каждого «оптимизированного» прогона.9

Дискуссионные вопросы и противоречия

«Меньше allocated — значит эффективнее». README Senpai справедливо различает allocated memory и требуемый working set и предлагает искать границу через PSI и cgroup limits. Но это позиция авторов инструмента и пример их workload, не универсальная измеренная экономия для VPS. Слишком сильное сокращение cache переводит стоимость из памяти во время; цель администратора — полезный сервис, а не минимальный memory graph.172

«PSI снизился — foreground ускорился». Препринт Dhakal и Sigdel сравнивает static zram, delayed activation и однократный bounded reclaim. Авторы видят зависимость эффекта от foreground-workload; улучшение относительно static zram для SQLite не установлено. Их собственный вывод ограничен:

“The predefined all-four rule therefore reports no general responsiveness benefit and no detected harm.”18

Это не доказательство бесполезности reclaim и не подтверждение эквивалентности вариантов: работа сама ограничивает переносимость однородными VM, синтетической фоновой нагрузкой и двумя canaries. Она полезна здесь как контраргумент к автоматическому переходу от успешного механизма к общему обещанию latency. Препринт не воспроизводился в этом обзоре.18

«Swap всегда мешает» против «без swap безопаснее». Частые обращения к дисковому swap имеют performance penalty, но systemd-oomd рекомендует swap как временной буфер для реакции. Противоречия в механике нет: один документ говорит о стоимости доступа, другой — о времени до аварии. Правильное решение зависит от того, приемлемее ли замедление, ранняя остановка background или немедленный отказ allocation.144

«Защитим всё важное». memory.min и memory.low перераспределяют reclaim pressure, не увеличивая физический ресурс. Если всё объявлено защищённым, сама политика перестаёт выражать приоритеты; при жёсткой чрезмерной защите появляются OOM. Нужен явный класс работы, который разрешено замедлить и потерять, а не одинаковые обещания каждому сервису.13

Недостаточность данных

Из прочитанных документов нельзя определить оптимальные размеры high/max/low для конкретного VPS, приемлемый PSI threshold или выигрыш p99. Неизвестны workload, пики при восстановлении, сжимаемость данных, скорость storage и внешняя конкуренция гостя. Поэтому численный бюджет выше остаётся гипотезой; результаты локального pressure-test в статье отсутствуют.

Также не установлено, как именно конкретная установленная версия Docker/Compose переводит все параметры в cgroup files, и поддерживает ли конкретный сервис pressure protocol systemd. Прочитаны описания интерфейсов, а не обследован deployment. Для применения нужны отдельные проверки effective limits, placement, кандидатов oomd и восстановления данных.

Заключение

Память на shared VPS стоит распределять не по списку процессов, а по классам допустимой деградации. Практический порядок: учесть всю память группы, выделить прерываемую ветвь, проверить ограничения предков, выбрать high как управляемую зону давления и max как аварийную границу. Защиту foreground нужно проводить по иерархии, а не выдавать локально красивым числом.136

PSI дополняет этот бюджет ценой ожидания, но не подменяет latency и ошибки приложения. Хорошая политика освобождает ресурс или уменьшает поступающую работу; плохая лишь надолго удерживает сервис в reclaim. systemd-oomd может ограничить время такого состояния ценой уничтожения workload, поэтому его граница должна совпадать с тем, что действительно разрешено остановить.2412

Итог: искать следует не «процент памяти, при котором Linux справится», а проверяемую границу между нормальной работой, уступкой ресурса и отказом. Документы дают механизмы; рабочие числа и приемлемость отказа устанавливает только испытание собственной нагрузки.

Quality Metrics

MetricValue
Sources found70
Sources read18
Sources cited18
Academic sources1
Official/documentation17
Industry reports0
News/journalism0
Blog/forum0
Citation coverage84% (51/61 substantive paragraphs, checker)
Main-text words3174; без frontmatter, Quality Metrics и footnotes
Checker words3530; более широкий подсчёт, включая метрики и библиографию
Counter-arguments searchedYes
Research rounds2
Questions emerged3
Questions resolved2
Questions insufficient data1
Count unitsFound — уникальные candidate URL, включая нерелевантные и недоступные; read/cited — документы, без удвоения raw/HTML представлений
Independence18 документов не означают 18 независимых измерений; преобладают документы Linux, systemd и Docker
Access scopeРелевантные полнотекстовые разделы всех цитируемых документов; препринт — методы, результаты, ограничения
Version boundaryLinux v6.12, systemd v257; Docker Docs и README Senpai — снимок на 2026-11-12
Empirical executionНе проводилось; бюджет и pressure-test — предложения автора

  1. Linux contributors. “Control Group v2.” Linux v6.12, Documentation/admin-guide/cgroup-v2.rst. https://github.com/torvalds/linux/blob/v6.12/Documentation/admin-guide/cgroup-v2.rst ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  2. Linux contributors. “PSI - Pressure Stall Information.” Linux v6.12, Documentation/accounting/psi.rst. https://github.com/torvalds/linux/blob/v6.12/Documentation/accounting/psi.rst ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  3. systemd contributors. “systemd.resource-control.” systemd v257, man/systemd.resource-control.xml. https://github.com/systemd/systemd/blob/v257/man/systemd.resource-control.xml ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  4. systemd contributors. “systemd-oomd.service.” systemd v257, man/systemd-oomd.service.xml. https://github.com/systemd/systemd/blob/v257/man/systemd-oomd.service.xml ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  5. Linux contributors. “The /proc Filesystem.” Linux v6.12, Documentation/filesystems/proc.rst. https://github.com/torvalds/linux/blob/v6.12/Documentation/filesystems/proc.rst ↩︎ ↩︎ ↩︎ ↩︎

  6. systemd contributors. “systemd.slice.” systemd v257, man/systemd.slice.xml. https://github.com/systemd/systemd/blob/v257/man/systemd.slice.xml ↩︎ ↩︎ ↩︎

  7. systemd contributors. “systemd.service.” systemd v257, man/systemd.service.xml. https://github.com/systemd/systemd/blob/v257/man/systemd.service.xml ↩︎ ↩︎ ↩︎

  8. systemd contributors. “systemd-run.” systemd v257, man/systemd-run.xml. https://github.com/systemd/systemd/blob/v257/man/systemd-run.xml ↩︎

  9. Linux contributors. “Documentation for /proc/sys/vm/.” Linux v6.12, Documentation/admin-guide/sysctl/vm.rst. https://github.com/torvalds/linux/blob/v6.12/Documentation/admin-guide/sysctl/vm.rst ↩︎ ↩︎

  10. Linux contributors. “Overcommit Accounting.” Linux v6.12, Documentation/mm/overcommit-accounting.rst. https://github.com/torvalds/linux/blob/v6.12/Documentation/mm/overcommit-accounting.rst ↩︎

  11. Linux contributors. “zram: Compressed RAM-based block devices.” Linux v6.12, Documentation/admin-guide/blockdev/zram.rst. https://github.com/torvalds/linux/blob/v6.12/Documentation/admin-guide/blockdev/zram.rst ↩︎

  12. systemd contributors. “Memory Pressure Handling in systemd.” systemd v257, docs/MEMORY_PRESSURE.md. https://github.com/systemd/systemd/blob/v257/docs/MEMORY_PRESSURE.md ↩︎ ↩︎

  13. systemd contributors. “oomd.conf.” systemd v257, man/oomd.conf.xml. https://github.com/systemd/systemd/blob/v257/man/oomd.conf.xml ↩︎

  14. Docker. “Resource constraints.” Docker Docs, прочитано 2026-11-12. https://docs.docker.com/engine/containers/resource_constraints/ ↩︎ ↩︎ ↩︎

  15. Docker. “Define services in Docker Compose.” Docker Docs, прочитано 2026-11-12. https://docs.docker.com/reference/compose-file/services/ ↩︎ ↩︎

  16. Docker. “docker container run.” Docker Docs, прочитано 2026-11-12. https://docs.docker.com/reference/cli/docker/container/run/ ↩︎

  17. Meta / facebookincubator. “Senpai.” README, прочитано 2026-11-12. https://github.com/facebookincubator/senpai ↩︎

  18. Abhiyan Dhakal, Sanjog Sigdel. “A Bounded Reclaim Actuator for PSI-Guided Compressed Memory: A Controlled Ablation.” arXiv:2608.13689v1, 2026-08-13, препринт. https://arxiv.org/html/2608.13689v1 ↩︎ ↩︎