Компьютер зависает почти на ОЗУ, возможно, проблема с дисковым кешем

75

Проблема, я думаю, чем-то похожа на эту тему.

Неважно, если я включил или отключил обмен, всякий раз, когда объем реально используемой оперативной памяти начинает приближаться к максимальному и почти не остается места для дискового кэша, система перестает отвечать на запросы.

Диск крутится дико, и иногда после долгого ожидания 10-30 минут он разморозится, а иногда нет (или у меня кончится терпение). Иногда, если я действую быстро, мне удается медленно открыть консоль и убить некоторые приложения, которые едят оперативную память, например браузер, и система почти мгновенно размораживается.

Из-за этой проблемы я почти никогда не вижу ничего в свопе, только иногда там есть несколько МБ, а затем вскоре после того, как эта проблема появляется. Мое не очень образованное предположение состояло бы в том, что он каким-то образом связан с слишком жадным дисковым кешем или слишком мягким управлением памятью, поэтому, когда память требуется, она не освобождается достаточно быстро и приводит к голоданию системы.

Проблема может быть решена очень быстро, если работать с файлами lagrge (500 МБ +), которые загружаются в дисковый кеш, и после этого система не может выгрузить их достаточно быстро.

Любая помощь или идеи будут с благодарностью.

Сейчас мне приходится жить в постоянном страхе, когда что-то делает компьютер, который может просто зависнуть, и мне, как правило, приходится перезапускать его, если он действительно исчерпывает себя, мне бы очень хотелось, чтобы он просто убивал некоторые приложения пользовательского пространства, такие как broser ( желательно, если бы я мог как-то отметить, кого убить первым)

Хотя загадка - вот почему своп не спас меня в этой ситуации.

ОБНОВЛЕНИЕ: Это не висело в течение некоторого времени, но теперь я снова получил несколько происшествий. Сейчас я постоянно держу монитор памяти на своем экране, и когда зависание происходило, оно все равно показывало ~ 30% свободного места (вероятно, используется дисковым кешем). Дополнительные симптомы: Если во время просмотра видео (проигрыватель VLC) звук останавливается первым, через несколько секунд изображение останавливается. Хотя звук прекратился, я все еще имею некоторый контроль над ПК, но когда изображение останавливается, я даже больше не могу двигать мышью, поэтому я перезапустил его после некоторого ожидания. Между прочим, этого не произошло, когда я начал смотреть видео, но некоторое время спустя (20 минут) и в то время я больше ничего не делал активно, хотя браузер и oowrite были открыты на втором экране все время. По сути, что-то просто решает произойти в какой-то момент, и система зависает.

По запросу в комментариях я запускал dmesg сразу после зависания. Я не заметил ничего странного, но не знал, что искать, поэтому вот оно: https://docs.google.com/document/d/1iQih0Ee2DwsGd3VuQZu0bPbg0JGjSOCRZhu0B05CMYs/edit?hl=en_US&authbcCz7

Кришьянис Несенбергс
источник
11
Это должно привлечь больше внимания. Я знаю, что есть ошибки, хранящиеся много-много лет.
3
1
@ n3rd: это ошибка .
Дан Даскалеску
@ Krišjānis Nesenbergs: Пожалуйста, исправьте меня, если я ошибаюсь, копирование при вставке длинного файла также приводит к зависанию.
Rick2047
Спасибо, что задали этот вопрос и нашли решение. Пожалуйста, добавьте дату к обновлению, в противном случае не ясно, что сработало, а что не сработало. У меня одна и та же проблема, я всегда проверяю уровни памяти, и у меня есть 16 ГБ, я планирую иметь 32 ГБ, чтобы посмотреть, смогу ли я исправить это таким образом ...
Beto Aveiga

Ответы:

63

Чтобы решить эту проблему, я обнаружил, что вам нужно установить следующий параметр примерно в 5% -6% от общей физической памяти, разделенный на количество ядер в компьютере:

sysctl -w vm.min_free_kbytes=65536

Имейте в виду, что это настройка для каждого ядра, поэтому, если у меня 2 ГБ ОЗУ и два ядра, я рассчитал 6% только из 1 ГБ и добавил немного больше, чтобы быть в безопасности.

Это заставляет компьютер пытаться освободить этот объем ОЗУ, и при этом ограничивает возможность кэширования файлов на диске. Конечно, он все еще пытается их кешировать и немедленно поменять их местами, так что вам, вероятно, следует также ограничить обмен:

sysctl -w vm.swappiness=5

(100 = своп как можно чаще, 0 = своп только по полной необходимости)

В результате linux больше не принимает случайного решения загрузить весь файл фильма объемом около 1 ГБ в оперативной памяти во время просмотра, что приводит к гибели компьютера.

Теперь есть достаточно зарезервированного пространства, чтобы избежать истощения памяти, что, по-видимому, было проблемой (поскольку больше нет зависаний, как раньше).

После тестирования в течение дня - блокировки исчезли, иногда бывают небольшие замедления, потому что вещи чаще кэшируются, но я могу с этим смириться, если мне не нужно перезагружать компьютер каждые несколько часов.

Урок здесь заключается в том, что управление памятью по умолчанию является лишь одним из вариантов использования и не всегда является лучшим, хотя некоторые люди пытаются предложить иное - Ubuntu для домашних развлечений следует настраивать не так, как сервер.


Возможно, вы захотите сделать эти настройки постоянными, добавив их в ваш файл /etc/sysctl.confследующим образом:

vm.swappiness=5
vm.min_free_kbytes=65536
Кришьянис Несенбергс
источник
1
Хорошая находка, попробуйте сообщить об ошибках, чтобы лучше осознать проблему, и, надеюсь, кто-то найдет решение не загружать весь фильм случайным образом,
Oxwivi
спасибо, очень подробно и объясняет мою проблему. Очень признателен!
odedbd
1
Ну, я перепробовал почти все, и только твое предложение улучшило ситуацию. спасибо
виталий
1
Если я работаю без раздела подкачки, я должен использовать больше, чем 5-6%? А настройка vm.swappinessничего не даст в таком случае, я полагаю?
Джаретт Миллард
1
«[vm.min_free_kbytes] заставляет компьютер пытаться освободить этот объем оперативной памяти, и при этом ограничивает возможность кэширования файлов на диске». - Извините, что беспокою, но это не связано с тем, что vm.min_free_kbytesвообще делает. Он действует как блок страниц, зарезервированных для облегчения атомарного (т. Е. Заполнения или уничтожения / отсутствия __GFP_WAIT) распределения в условиях высокой конкуренции системной памяти. Здесь действительно может иметь смысл поднять этот вопрос (поскольку, вероятно, эти киоски связаны с конфликтом системной памяти), но это точно не будет причиной, описанной в этом ответе.
Крис Даун
9

Это произошло для меня в новой установке Ubuntu 14.04.

В моем случае это не имело никакого отношения к упомянутым проблемам sysctl.

Вместо этого проблема заключалась в том, что UUID раздела подкачки во время установки отличался от того, который был после установки. Так что мой своп никогда не был включен, и мой компьютер зависал после нескольких часов использования.

Решение было проверить текущий UUID раздела подкачки с

sudo blkid

а затем sudo nano /etc/fstabзаменить неверное значение UUID свопа на значение, указанное в blkid.

Простая перезагрузка, чтобы повлиять на изменения, и вуаля.

Дейл Андерсон
источник
3
Спасибо вам большое! Я боролся с этой невероятно бешеной ошибкой вот уже около года и пытался все исправить. Почему в Linux такое поведение? Кажется, он должен действовать так, как будто нет свопа, и просто вызывать OOM-убийцу. Вместо этого он, кажется, делает вид, что есть своп, но затем не может на самом деле поменять вещи (потому что на самом деле это не так, поскольку он неправильно настроен).
crazy2be
@ crazy2be Это не провал, это преуспевает бесконечно. Даже без какой-либо подкачки, Linux все еще может выгружать программы и неизмененные файлы в памяти и перечитывать их с диска.
Мартин Торнтон
5

Я знаю, что этот вопрос старый, но у меня была эта проблема в Ubuntu (Chrubuntu) 14.04 на Chromebook Acer C720. Я попробовал решение Krišjānis Nesenbergs, и оно несколько сработало, но иногда все же падало.

Наконец-то я нашел решение, которое сработало, установив zram вместо физического подкачки на SSD. Чтобы установить его, я просто следовал инструкциям здесь , вот так:

sudo apt-get install zram-config

После этого мне удалось настроить размер zram swap, изменив /etc/init/zram-config.confстроку 21.

20: # Calculate the memory to user for zram (1/2 of ram)
21: mem=$(((totalmem / 2 / ${NRDEVICES}) * 1024))

Я заменил 2 на 1, чтобы размер zram соответствовал размеру барана. С тех пор у меня больше не было зависаний или системного бездействия.

brismuth
источник
zramЭто жизнеспособный вариант, только если вы не можете установить больше оперативной памяти. Если система работает слишком медленно при переключении на SSD и выходит из ОЗУ без подкачки, это zramможет помочь немного, пока вы не попытаетесь сделать немного больше, и результат будет таким же, как и из ОЗУ без подкачки.
Микко Ранталайнен
5

У меня ничего не получалось !!

Поэтому я написал скрипт для мониторинга использования памяти. Сначала он попытается очистить кэш ОЗУ, если потребление памяти увеличит порог. Вы можете настроить этот порог в сценарии. Если даже тогда потребление памяти не будет ниже порогового значения, оно начнет убивать процессы на один в порядке убывания потребления, пока потребление памяти не станет ниже порогового значения. Я установил его на 96% по умолчанию. Вы можете настроить его, изменив значение переменной RAM_USAGE_THRESHOLD в скрипте.

Я согласен, что процессы уничтожения, которые занимают много памяти, не являются идеальным решением, но лучше убить ОДНО приложение, а не терять ВСЕ работу !! сценарий отправит вам уведомление на рабочем столе, если использование ОЗУ увеличит порог. Он также уведомит вас, если убьет какой-либо процесс.

#!/usr/bin/env python
import psutil, time
import tkinter as tk
from subprocess import Popen, PIPE
import tkinter
from tkinter import messagebox
root = tkinter.Tk()
root.withdraw()

RAM_USAGE_THRESHOLD = 96
MAX_NUM_PROCESS_KILL = 100

def main():
    if psutil.virtual_memory().percent >= RAM_USAGE_THRESHOLD:
        # Clear RAM cache
        mem_warn = "Memory usage critical: {}%\nClearing RAM Cache".\
            format(psutil.virtual_memory().percent)
        print(mem_warn)
        Popen("notify-send \"{}\"".format(mem_warn), shell=True)
        print("Clearing RAM Cache")
        print(Popen('echo 1 > /proc/sys/vm/drop_caches',
                    stdout=PIPE, stderr=PIPE,
                    shell=True).communicate())
        post_cache_mssg = "Memory usage after clearing RAM cache: {}%".format(
                            psutil.virtual_memory().percent)
        Popen("notify-send \"{}\"".format(post_cache_mssg), shell=True)
        print(post_cache_mssg)

        if psutil.virtual_memory().percent < RAM_USAGE_THRESHOLD:
            print("Clearing RAM cache saved the day")
            return
        # Kill top C{MAX_NUM_PROCESS_KILL} highest memory consuming processes.
        ps_killed_notify = ""
        for i, ps in enumerate(sorted(psutil.process_iter(),
                                      key=lambda x: x.memory_percent(),
                                      reverse=True)):
            # Do not kill root
            if ps.pid == 1:
                continue
            elif (i > MAX_NUM_PROCESS_KILL) or \
                    (psutil.virtual_memory().percent < RAM_USAGE_THRESHOLD):
                messagebox.showwarning('Killed proccess - save_hang',
                                       ps_killed_notify)
                Popen("notify-send \"{}\"".format(ps_killed_notify), shell=True)
                return
            else:
                try:
                    ps_killed_mssg = "Killed {} {} ({}) which was consuming {" \
                                     "} % memory (memory usage={})". \
                        format(i, ps.name(), ps.pid, ps.memory_percent(),
                               psutil.virtual_memory().percent)
                    ps.kill()
                    time.sleep(1)
                    ps_killed_mssg += "Current memory usage={}".\
                        format(psutil.virtual_memory().percent)
                    print(ps_killed_mssg)
                    ps_killed_notify += ps_killed_mssg + "\n"
                except Exception as err:
                    print("Error while killing {}: {}".format(ps.pid, err))
    else:
        print("Memory usage = " + str(psutil.virtual_memory().percent))
    root.update()


if __name__ == "__main__":
    while True:
        try:
            main()
        except Exception as err:
            print(err)
        time.sleep(1)

Сохраните код в файле скажем save_hang.py. Запустите скрипт как:

sudo python save_hang.py

Обратите внимание, что этот скрипт совместим только с Python 3 и требует установки пакета tkinter. Вы можете установить его как:

sudo apt-get install python3-tk

Надеюсь это поможет...

Саим Раза
источник
2

Я предполагаю, что вы установили vm.swappinessочень низкое значение, из-за чего ядро ​​переставляется слишком поздно, оставляя слишком мало оперативной памяти для работы системы.

Вы можете показать текущую настройку подкачки, выполнив:

sysctl vm.swappiness

По умолчанию это значение равно 60. Ubuntu Wiki рекомендует установить значение 10, но вы можете установить более высокое значение. Вы можете изменить это, запустив:

sudo sysctl vm.swappiness=10

Это изменит его только для текущего сеанса , чтобы сделать его постоянным, необходимо добавить vm.swappiness = 10его в /etc/sysctl.confфайл.

Если у вас медленный диск, подумайте о покупке нового.

Lekensteyn
источник
На самом деле уменьшение свопинга уменьшило проблему (это случалось реже). Я держу это в 5 теперь. Хотя, возможно, это была еще одна проблема с более высокой степенью подкачки, потому что, когда ей было 60 лет, и я решил посмотреть фильм или отредактировать большой файл, в память был загружен целый файл, например, почти ГБ, а затем система сразу же начала выгружать программы, которыми я занимался. активно использует и даже сам пользовательский интерфейс. Дело в том, что я думаю, что понимаю часть обмена: я хочу убивать жадных пользовательских приложений, а не замораживать машину, когда у нее заканчивается оперативная память. (И желательно ограничить размер файла в кеше)
Кришянис Несенбергс
@ Krisa: когда системе не хватает памяти (RAM и swap), ядро ​​вызывает oom_kill, который убивает процессы для экономии памяти. К сожалению, вы не можете контролировать целевые процессы. Чтобы запустить его вручную, нажмите Alt + SysRq + F. При запуске dmesgкоманды вы должны увидеть некоторую информацию (и имя процесса + идентификатор) процесса. Я думаю, вам лучше купить новый, более быстрый диск. Или обновите свою RAM.
Лекенштейн
3
Проблема в том, что oom_kill просто не вызывают до тех пор, пока компьютер не будет заблокирован примерно на 30 минут. Кроме того - есть ли хотя бы способ узнать, какой процесс будет убит первым?
Кришьянис Несенбергс
2
У меня 2 ГБ оперативной памяти, а жесткий диск составляет 5400 об / мин. Я действительно не думаю, что это такая старая система, которая оправдывает полчаса зависаний при просмотре видео на одном мониторе и просмотре 20-30 вкладок на другом. На самом деле я был бы весьма счастлив, если бы я мог всегда получить доступ к консоли и убить некоторые процессы - есть ли способ сделать пользовательский ввод и терминал сверхвысоким приоритетом, чтобы он работал, пока система зависает?
Кришьянис Несенбергс
1
В любом случае - подкачка и объем оперативной памяти немного оффтопичны. Проблема в том, что система перестает отвечать на запросы в течение долгого времени, даже если подкачка отключена, и после этого иногда по-прежнему запускает программу (поэтому ей удается где-то найти память), а иногда запускает oom_killer. Система должна быть в состоянии сказать, что она исчерпала оперативную память и просто не позволяет мне запускать больше вещей. Так есть ли способ остановить эти зависания или установить приоритет ввода пользователя настолько высоким, чтобы я мог переключиться на консоль, когда они происходят, и сам убить некоторые процессы?
Кришьянис Несенбергс
2

Я долго боролся с этой проблемой, но теперь, похоже, она решается на моем ноутбуке.

Если ни один из других ответов не работает для вас (я пробовал большинство из них), поиграйтесь с min_free_kbytes , чтобы иметь больше места в оперативной памяти, когда ваш компьютер начинает подкачку (непосредственно перед достижением этого минимального значения в вашей свободной оперативной памяти).

У меня 16 ГБ ОЗУ, но раньше, чем позже, память заполнялась, а затем перестала отвечать на 10-30 минут, пока некоторые вещи не поменялись местами.

По крайней мере, для меня установка значения min_free_kbytes выше рекомендованного значительно ускоряет процесс обмена.

Для 16 ГБ ОЗУ попробуйте это:

vm.min_free_kbytes=500000

Чтобы установить это значение, смотрите другие ответы или просто гуглите его :)

Бето Авейга
источник
0

Я постоянно запускаю один из моих ноутбуков с живой SD-карты Ubuntu с небольшим разделом хранения ext4 и файлом подкачки на жестком диске. Когда используется почти вся оперативная память, а значение подкачки слишком низкое (иногда я предпочитаю полностью отключить жесткий диск, если это возможно, потому что он шумный), производительность Linux для меня имеет тенденцию падать с обрыва, так что просто TTY1, чтобы убить Firefox, занимает 15 минут.

Повышение /proc/sys/vm/vfs_cache_pressureзначения по умолчанию от 100 до 6000, кажется, помогает предотвратить это. Тем не менее, документация ядра предупреждает против этого, говоря

Increasing vfs_cache_pressure significantly beyond 100 may have negative
performance impact. Reclaim code needs to take various locks to find freeable
directory and inode objects. With vfs_cache_pressure=1000, it will look for
ten times more freeable objects than there are.

Я не совсем уверен в побочных эффектах этого, поэтому я буду осторожен в этом.

Hitechcomputergeek
источник
Вероятно, вы получите лучшие результаты при vfs_cache_pressureприближении к 10 (т. Е. Намного меньше 100) и настройке min_free_kbytesвыше. Имейте в виду, что если вы установите min_free_kbytesслишком высокое значение, ядро ​​OOM Killer убьет всех!
Микко Ранталайнен
@MikkoRantalainen Я уже повысил min_free_kbytesдо 262144, и я заметил, что снижение vfs_cache_pressureимеет противоположный эффект - снижение его ниже 100 заставляет систему перестать отвечать на запросы намного быстрее. Я не уверен, почему именно.
Hitechcomputergeek
В целом, увеличение vfs_cache_pressureприведет к тому, что директории будут выброшены раньше, чем содержимое кэшированного файла, и, как результат, общая производительность, как правило, пострадает со значениями более 100. Если вы сможете найти шаги для воспроизведения, чтобы вызвать сбой / зависание системы, например, с Ubuntu Live CD тогда разработчики ядра могут выяснить причину. Для меня зависание происходит без предупреждения. Я думаю, что ядро ​​зависает из-за OOM до того, как OOM Killer освободит достаточно оперативной памяти. Сейчас я запускаю min_free_kbytes = 100000, admin_reserve_kbytes = 250000 и user_reserve_kbytes = 500000.
Микко Ранталайнен
(продолжение) Я еще не разбился с вышеуказанным конфигом, хотя у меня есть swappiness = 5 и vfs_cache_pressure = 20. Система имеет 16 ГБ оперативной памяти и 8 ГБ подкачки на SSD. Другая система имеет 32 ГБ ОЗУ и нулевой своп, и кажется, что она случайно страдает от той же самой проблемы - там, нажимая Alt + SysRq + f после того, как система чувствует себя медленно, похоже, помогает, поэтому я предполагаю, что если OOM Killer действовал достаточно быстро, система не зависала.
Микко Ранталайнен