Нехватка оперативной памяти в Linux на рабочем ПК: оптимизация и действия при зависании

    На любой операционной системе часто не хватает оперативной памяти. Рассмотрим, как и сэкономить на увеличении аппаратных ресурсов машины с Linux, и продолжить более-менее комфортно пользоваться компьютером с Linux в условиях нехватки памяти.

    Типична такая ситуация: есть своп (swap, раздел подкачки), который начинает использоваться при нехватке оперативной памяти, и размещен он на HDD, то есть жестком диске с низкой скоростью чтения информации. В таких ситуациях операционная система начинает тормозить, подвисает курсор мыши, сложно переключиться в соседнюю tty и т.д. Почему? Потому что планировщик ядра Linux не может выполнить запрос на какое-то действие в запущенной программе, пока не получит доступ к ее оперативной памяти, выполнить следующее действие тоже не может, образовывается очередь из запросов на чтение с диска, и система «подвисает» именно потому, что обработка очереди происходит гораздо медленнее, чем этого хочет пользователь.

    Если в такой момент запустить htop или uptime, то показатель Load Average (LA) будет очень высоким, несмотря на низкую загруженность ядер процессора. Сочетание высокого Load Average и низкой загрузки процессора говорят о забитой очереди процессора.

    Часто в интернете советуют изменить параметр ядра Linux vm.swappiness. Узнать его текущее значение на вашей системе можно так:

    sysctl vm.swappiness

    Ответ будет 60 почти наверняка. Это значит, что ядро Linux начинает свопить редко используемые страницы оперативной памяти, когда использование свободной оперативной памяти достигает 100%-60%=40%. Часто встречаются рекомендации поставить, например, vm.swappiness=10, чтобы своп не начинал использоваться, пока загрузка ОЗу не достигнет 90%. На самом деле не нужно трогать vm.swappiness, вы не умнее разработчиков ядра Linux, которые не просто так поставили 60 по умолчанию. Почему?

    Представьте, что у вас всего 4 ГБ оперативной памяти, из них прямо сейчас занято 3 ГБ, vm.swappiness=10, своп на жестком диске (HDD) занят на 0%, и вы открываете тяжелый сайт в браузере, для чего требуется больше, чем имеющийся свободный 1 ГБ, например, 2 ГБ. Операционная система начинает в экстренном порядке отправлять в своп как минимум 0.5 ГБ (а по факту больше), чтобы можно было выделить браузеру необходимое количество оперативной памяти. Эта процедура становится самой приоритетной задачей, и придется пожертвовать даже движениями курсора мыши, чтобы ее выполнить как можно быстрее. Вы ждете. Проходит 5 минут, и система развисает, потому что окончила процедуру 100% загрузки очереди доступа к медленному жесткому диску, на котором размещена оперативная память (своп). При дефолтном vm.swappiness=60 редко используемые страницы памяти сбрасываются в своп заблаговременно, и резкого зависания на 5-10 минут не происходит.

    zram и приоритеты свопов


    Рекомендую включить zram — прозрачное сжатие содержимого оперативной памяти. В Ubuntu это автоматизировано, достаточно установить пакет:

    sudo apt install zram-config

    Здесь и далее для дистрибутивов Rosa, Fedora все то же самое, но вместо zram-config —

    zram-start.

    Сервис systemd zram-config на Ubuntu будет автоматически добавлен в автозагрузку при установке пакета и запущен при перезагрузке системы. Для запуска вручную:

    sudo systemctl start zram-config

    остановки:

    sudo systemctl stop zram-config

    Удаления из автозапуска:

    sudo systemctl disable zram-config

    Добавление в автозапуск:

    sudo systemctl enable zram-config

    При запуске zram-config берет число, равное 50% всего объема оперативной памяти, далее делает по одному виртуальному устройству /dev/zramN, где N начинается с 0, для каждого ядра процессора, а объем каждого /dev/zramN равен 50% всей оперативной памяти, деленному на количество ядер процессора. Так делалается для распараллеливания сжатия содержимого оперативной памяти по ядрам процессора; насколько я знаю, на современных ядрах Linux достаточно одного устройства /dev/zramN, а распараллелится оно само, но меня полностью устраивает искоробочная работа zram-config, и предпочитаю не лезть в нее руками.

    Команда swapon -s выведет список всех задействованных свопов с указанием их приоритета. Первым используется тот своп, у которого приоритет выше. Если у вас уже есть дисковый своп и включен zram, то в случае с описанным выше пакетом-автокофигуратором приоритеты из коробки будут правильными. Например, у дискового свопа будет -1, а все /dev/zramN — 5. Таким образом, сначала используется zram, и только потом — диск.

    Кстати, zram часто применяется на смартфонах, какую-либо на глаз заметную нагрузку на процессор при дефолтном методе сжатия lz4 он не создает.

    Также приоритет свопа можно указать в /etc/fstab. Покажу на примере, как это сделано на моем рабочем компьютере с 6 ГБ ОЗУ.

    $ cat /etc/fstab | grep  swap
    # swap на SSD
    UUID=844fc9fb-509d-4dab-9ea5-a3d5142f76d8 none    swap    sw,pri=2      0       0
    # swap на HDD для гибернации
    UUID=b643c42a-0abd-4f35-8865-7a51be5769e8 none    swap    sw,pri=1     0       0
    

    Опцией монтирования pri=X заданы приоритеты свопов. Если еще включить zram, то картинка будет такой:

    $ swapon -s
    Filename	 	  Type		Size	Used Priority
    /dev/sdb3         partition	1005564	0	2
    /dev/sda2         partition	6655996	0	1
    /dev/zram0        partition	690764	0	5
    /dev/zram1        partition	690764	0	5
    /dev/zram2        partition	690764	0	5
    /dev/zram3        partition	690764	0	5
    

    В первую очередь будет свопиться в zram, то есть сжиматься внутри оперативной памяти без использования внешнего устройства для свопа, во вторую — использовать небольшой своп на SSD. Почти никогда не будет использоваться 6 ГБ свопа на HDD, однако они понадобятся, если я захочу отправить компьютер в спящий режим в условиях большой загрузки оперативной памяти. (На самом деле у меня отключен zram).

    На офисных ПК с 4 ГБ ОЗУ (Xubuntu 16.04, 17.10) всегда ставлю пакет zram-config. Chromium, по наблюдениям, на глаз, очень хорошо сжимается в оперативной памяти, в результате чего zram позволяет сделать работу намного более комфортной без модернизации железа.

    Быстро вырубить программу, перегружающую ОЗУ. Запас ОЗУ для SSH


    Бывает такое, что даже при vm.swappiness=60 какому-то черту, как правило, браузеру, требуется очень много оперативной памяти, и система подвисает. Решается очень просто: сочетание клавиш Alt+SysRq(PrintScreen)+F заставляет oom_killer принудительно включиться и вырубить процесс, который на момент вызова занимает больше всего памяти. Строго 1 процесс на 1 вызов, и строго обязательно что-то будет убито. Если много раз подряд нажмете, то, скорее всего, перезапустится графическая сессия. Событие убиения процесса отражается в dmesg красным цветом.

    Однако эта штука, называющаяся Magic SysRq, из коробки отключена в большинстве дистрибутивов, потому что непривилегированный пользователь может убить абсолютно любой процесс. За это отчечает параметр ядра kernel.sysrq, узнать его текущее значение можно так:

    sysctl kernel.sysrq.

    Для работы Alt+SysRq+F нужно kernel.sysrq=1. Для этого отредатируем параметры ядра, расположенные в файлах /etc/sysctl.conf (обычно симлинк на /etc/sysctl.d/99-sysctl.conf) и /etc/sysctl.d/*.conf. Лучше всего создать отдельный файл:

    sudo nano /etc/sysctl.d/99-dumalogiya.conf

    В него запишем:

    # включить все комбинации Alt+SysRq, в т.ч. Alt+SysRq+F для принудительного вызова OOM Killer
    kernel.sysrq = 1
    # с 8 МБ увеличим размер памяти, который будет гарантированно не занят в системе, чтобы у нас могли работать SSH и пр.
    vm.admin_reserve_kbytes = 60192
    

    Нажмем Ctrl+O, Enter для сохранения.

    В случае с браузером Chromium Alt+SysRq(PrintScreen)+F будет вырубать по одной вкладке, не закрывая сам браузер, что очень удобно.



    Сочетания клавиш Magic SysRq перехватываются напрямую ядром Linux, поэтому работают даже когда из-за очереди процессора подвисает X-сервер.

    vm.admin_reserve_kbytes — это размер оперативной памяти в килобайтах, который будет держаться гарантированно свободным для административных нужд, например, работы SSH. По умолчанию что-то около 8 МБ. Целесообразно увеличить, число 60192 почти от балды.

    Я опакетил файл /etc/sysctl.d/99-dumalogiya.conf в deb-пакет dumalogiya-sysctl, который положил в свой репозиторий и ставлю на все компьютеры, очень удобно, можно централизованно обновлять конфиг, и не нужно настраивать вручную каждую машину. В качестве инструкции по сборке простых deb-пакетов «на коленке» рекомендую https://debian.pro/1390. Репозиторий создал с помощью aptly, который просто создает структуру файлов и папок внутри директории веб-сервера.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 30
    • +1
      Нужно правильно читать советы. Такие советы дают, когда у вас по 10-16 ГБ, и вам своп бывает очень редко нужен.

      Ну или на серверах с бд.
      • +3
        Будьте внимательны: речь идёт про десктопные машины а не про сервера в данной статье.
        Для серверов БД (например для Оракла) редхат в руководстве по настройке рекомендует swapiness выставлять в 1 для RHEL 7
        • 0
          Кстати, интересно, можно ли установить низкий приоритет свопинга для отдельного приложения, того же MySQL, чтобы он не свопился, а другие свопились?
      • 0
        Если стоит SSD, то картинка немного другая получается. Например на макбуке с 16Гб памяти постоянно что-нибудь лежит в свопе несмотря на 50% свободной оперативки.
        • 0
          Принцип работы ОС со свопом не зависит от типа носителя SSD/HDD.
          • 0
            Это да, но в зависимости от скорости накопителя зависит эффективность использования свопа и плавность работы. На SSD можно swappiness больше поставить.
            • –1
              И быстрее убить SSD…
              Не так давно у знакомых пролетал SSD, который из-за свопа за полтора года загнулся…
              • 0
                Уверены, что из-за свопа? Своп может только исчерпать лимит перезаписи ячеек, а это сделать очень сложно, и накопитель после этого не «летит», а блокирует запись, данные никуда не деваются.
                • 0
                  Не похоже на правду, у ССД сейчас наработка на отказ 5 лет, это значит не 5 лет эксплуатации, а непрерывной работы в 100% нагрузке.
                  • 0
                    Bad luck. На маках, например, своп управляется автоматически — его размер и использование. Пока ещё не слышал, чтобы у кого-то диск полетел не то чтобы через полтора года, но и через четыре года использования, например.
            • +4
              Это значит, что ядро Linux начинает свопить редко используемые страницы оперативной памяти, когда использование свободной оперативной памяти достигает 100%-60%=40%.

              Очень распространенное заблуждение. На самом деле vm.swappines делает следующее:
              This control is used to define how aggressive the kernel will swap
              memory pages. Higher values will increase aggressiveness, lower values
              decrease the amount of swap. A value of 0 instructs the kernel not to
              initiate swap until the amount of free and file-backed pages is less
              than the high water mark in a zone.

              (Из документации к ядру). Уже отсюда ясно, что никакого отношения к % свободной памяти эта настройка не имеет.
              Чуть подробнее о работе этой опции рассказано на портале Red Hat:
              A value from 0 to 100 which controls the degree to which the system favors anonymous memory or the page cache. A high value improves file-system performance, while aggressively swapping less active processes out of physical memory. A low value avoids swapping processes out of memory, which usually decreases latency, at the cost of I/O performance. The default value is 60.

              То есть опция указывает приоритет дискового кэша перед данными приложений. Поэтому уменьшение этой опции увеличивает приоритет данных приложений, взамен ухудшается кэширование I/O.
              • 0
                +1
                Более того совсем не понятно что такое "% свободной памяти", поскольку само понятие свободная память (особенно при разрешенном оверкоммите) это тема для еще нескольких статей.
              • +1
                А нет ли в Линуксе способа задать для каждого процесса (или некоторых) лимиты памяти и, если этот лимит превышен, останавливать процесс и спрашивать пользователя «увеличить временно лимит памяти процессу ХХХ, завершить или перезапустить?»

                Было бы очень полезно сделать такое, как минимум, для табов в хроме. А если это сделать в хроме по умолчанию на всех платформах, глядишь, фронтенд-сообщество начнёт думать, как расходовать память экономно.
                • +1

                  Есть, называется cgroup. Правда по умолчанию оом просто прибьет процесс, когда память закончится. Что бы спрашивало надо писать какую то граф обвязку, которая будет мониторить кол-во занятой памяти и спрашивать у пользователя при приближении к лимиту.

                • 0
                  Спасибо, как раз была проблема оптимизации Ubuntu под лэптоп с 2 ГБ ОЗУ. Использование zram значительно улучшило картину.
                  • +2
                    А еще можно не устанавливать zram, а включить уже имеющийся в ядре zswap — в некоторых ситуациях работает намного быстрее!
                    www.hippolab.ru/linux-zswap-dayte-mashine-shans
                    • +1
                      Подтверждаю, здесь как включить zswap для Ubuntu.
                      • +1
                        А он не включен по дефолту?
                        У меня на более-менее чистой убунте
                        $ dmesg | grep -i zswap
                        [ 0.804964] zswap: loaded using pool lzo/zbud
                        • 0
                          По дефолту в Ubuntu 16.04 — zswap не включен.

                          Чтобы проверить включен ли zswap, нужно выполнить:
                          cat /sys/module/zswap/parameters/enabled
                          если результат будет Y, значит включен.

                          Чтобы проверить включен ли lz4 компрессор — выполнить:
                          dmesg | grep -i zswap
                          если результат — [ 0.715381] zswap: loaded using pool lz4/zbud (обратите внимание на цифру 4), то lz4 — включен.
                      • 0
                        Инструкция по установки zram на fedora copr.fedorainfracloud.org/coprs/antonpatsev/zram
                          • 0

                            У меня 8 ГБ ОЗУ, своп не используется. Иногда какой-то процесс отжирает всё ОЗУ, и система впадает в ступор минут на 20-30, непрерывно светя индикатором жёсткого диска. После этого этот процесс убивается, память освобождается и всё продолжает работать нормально. Но что происходит в эти 20-30 минут?

                            • 0
                              скорее всего, процесс не пытается выделить себе памяти больше, чем доступно, поэтому oom_killer его не трогает.
                              • +2
                                В это время ядро пытается освободить память для возможности выделить её запросившему процессу. Но из-за отсутствия свопа приходится освобождать страницы памяти, занятые под дисковый кеш и под код разделяемых библиотек и других процессов.
                                Но так как система у нас многозадачная, то при переключении процессов у нас постоянно происходит загрузка с диска кода и библиотек для текущего процесса и освобождение для этого памяти за счёт других процессов. И так — по кругу. В результате, то что могло выполниться за несколько секунд занимает много минут.
                                Через 20-30 минут жрущий память процесс убивается, его память освобождается и ядро наконец-то может однократно загрузить код библиотек и других процессов и больше его не выгружать. Работа системы нормализовалась.

                                Описание сильно упрощено, но суть такова.
                              • 0
                                Всегда хотел узнать, а не у кого нет проблем при исчерпании всей памяти? А то у меня попросту начинает зависать все, практически намертво, (ожидать переключения на консоль приходится 5+мин. это без учета запуска login)а также светится индикатор работы с диском, но вот свап при этом отключен, OOM срабатывает только при отключении overcommit или нажатии SysReq сочетания клавиш, уже все связаные с памятью sysctl настройки перепробовал, не чего не помогает, проявляется на всех используемых мной дистрибутивах
                                • 0
                                  Были. И свопа тоже не было. После описанного в статье (zram, swap на диске, vm.admin_reserve_kbytes) в целом исчезли или стали проявляться крайне редко, а Alt+SysRq+F спасает, когда нужно.
                                • 0
                                  А как это все реализовать на арче? Тот же zram
                                • 0
                                  del

                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.