Computador congelando na RAM quase cheia, possivelmente problema no cache do disco

74

O problema que eu acho é um pouco semelhante a este tópico.

Não importa se eu tenho a troca ativada ou desativada, sempre que a quantidade real de RAM usada começa a chegar perto do máximo e quase não resta espaço para o cache do disco, o sistema fica totalmente sem resposta.

O disco está girando descontroladamente e, às vezes, depois de longas esperas de 10 a 30 minutos, descongela e, às vezes, não (ou fico sem paciência). Às vezes, se eu agir rapidamente, consigo abrir lentamente o console e matar alguns aplicativos que comem ram, como o navegador, e o sistema descongela quase instantaneamente.

Devido a esse problema, quase nunca vejo nada no swap, apenas algumas vezes existem alguns MB lá e logo depois esse problema aparece. Meu palpite não tão educado seria que ele está conectado, de alguma forma, ao cache do disco ser muito ganancioso ou ao gerenciamento de memória muito branda; portanto, quando a memória é necessária, ela não é liberada com rapidez suficiente e deixa o sistema com fome.

O problema pode ser alcançado muito rápido se você trabalhar com arquivos lagrge (500 MB +) carregados no cache do disco e, aparentemente, depois o sistema não conseguir descarregá-los com rapidez suficiente.

Qualquer ajuda ou idéias serão muito apreciadas.

Por enquanto, tenho que viver com medo constante, ao fazer algo que o computador pode congelar e geralmente preciso reiniciá-lo; se estiver realmente sem memória RAM, gostaria muito mais de matar alguns aplicativos do espaço do usuário, como o broser ( de preferência se eu pudesse de alguma forma marcar qual matar primeiro)

Embora o mistério seja por que a troca não me salva nessa situação.

ATUALIZAÇÃO: Não travou por algum tempo, mas agora recebi várias ocorrências novamente. Agora, estou mantendo o monitor ram na tela o tempo todo e, quando o travamento aconteceu, ele ainda mostrava ~ 30% livre (provavelmente usado pelo cache de disco). Sintomas adicionais: se no momento em que estou assistindo um vídeo (reprodutor VLC), o som para primeiro, depois de alguns segundos a imagem para. Enquanto o som parou, ainda tenho algum controle sobre o PC, mas quando a imagem para, não consigo mais mover o mouse, por isso o reiniciei depois de alguma espera. Btw, isso não aconteceu quando comecei a assistir ao vídeo, mas em algum momento (20min) e não fiz nada mais ativamente no momento, mesmo que o navegador e oowrite estivessem abertos na segunda tela o tempo todo. Basicamente, alguma coisa decide acontecer em um ponto e trava o sistema.

Conforme solicitado nos comentários, executei o dmesg logo após o travamento. Não notei nada de estranho, mas não sabia o que procurar, então aqui está: https://docs.google.com/document/d/1iQih0Ee2DwsGd3VuQZu0bPbg0JGjSOCRZhu0B05CMYs/edit?hl=pt_BR&authkey=CPzF7bcC

Krišjānis Nesenbergs
fonte
11
Isso precisa receber mais atenção. Eu sei que existem erros arquivados por muitos e muitos anos.
N3rd 20/01
1
@ n3rd: Este é o bug .
Dan Dascalescu
@ Krišjānis Nesenbergs: Por favor, corrija-me se eu estiver copiando errado, colar um arquivo longo também o faz travar.
precisa saber é o seguinte
Obrigado por fazer esta pergunta e encontrar uma solução. Adicione uma data à atualização, caso contrário, não está claro o que funcionou e o que não funcionou. Estou tendo o mesmo problema, eu estou sempre verificando os níveis de memória, e eu tenho 16 GB, planejando ter 32GB, para ver se eu posso corrigi-lo assim ...
Beto Aveiga

Respostas:

63

Para corrigir esse problema, descobri que você precisa definir a seguinte configuração para algo entre 5% e 6% da sua RAM física total, dividida pelo número de núcleos no computador:

sysctl -w vm.min_free_kbytes=65536

Lembre-se de que essa é uma configuração por núcleo; portanto, se eu tiver 2 GB de RAM e dois núcleos, calculei 6% de apenas 1 GB e adicionei um pouco mais apenas para garantir a segurança.

Isso força o computador a tentar manter essa quantidade de RAM livre e, ao fazer isso, limita a capacidade de armazenar em cache os arquivos do disco. Obviamente, ele ainda tenta armazená-los em cache e trocá-los imediatamente; portanto, você provavelmente deve limitar sua troca também:

sysctl -w vm.swappiness=5

(100 = troca o mais rápido possível, 0 = troca apenas na necessidade total)

O resultado é que o linux não decide mais carregar aleatoriamente um arquivo de filme inteiro de aproximadamente 1 GB de RAM enquanto o assiste e acaba com a máquina.

Agora, há espaço reservado suficiente para evitar a falta de memória, o que aparentemente foi o problema (visto que não há mais congelamentos como antes).

Após o teste por um dia - os bloqueios acabaram, às vezes há lentidões menores, porque as coisas são armazenadas em cache com mais frequência, mas posso conviver com isso se não precisar reiniciar o computador a cada poucas horas.

A lição aqui é - o gerenciamento de memória padrão é apenas um dos casos de uso e nem sempre é o melhor, mesmo que algumas pessoas tentem sugerir o contrário - o entretenimento doméstico ubuntu deve ser configurado de maneira diferente do servidor.


Você provavelmente deseja tornar essas configurações permanentes adicionando-as ao seu /etc/sysctl.confcomo este:

vm.swappiness=5
vm.min_free_kbytes=65536
Krišjānis Nesenbergs
fonte
Bom encontrar, tentar reportar bugs sobre ele então não há mais consciência do problema e espero que alguém vai chegar a uma solução para não carregar aleatoriamente o filme inteiro,
Oxwivi
obrigado, grandes detalhes e explica meu problema. Muito apreciado!
precisa saber é
1
bem, eu tentei quase tudo, e apenas sua sugestão melhorou as coisas. obrigado
vitalii 29/02
1
Se estiver executando sem uma partição de troca, devo usar uma quantidade maior que 5-6%? E configuração vm.swappinessnão fará nada nesse caso, eu suponho?
Jarett Millard
1
"[vm.min_free_kbytes] força o computador a tentar manter essa quantidade de RAM livre e, ao fazer isso, limita a capacidade de armazenar em cache arquivos de disco". - Desculpe incomodar, mas isso não está relacionado ao que vm.min_free_kbytesfaz. Ele atua como um bloco de páginas reservadas para facilitar __GFP_WAITalocações atômicas (ou seja, preencher ou eliminar / não ) quando sob alta contenção de memória do sistema. De fato, poderia fazer sentido aumentá-lo aqui (como provavelmente essas paradas estão relacionadas à contenção de memória do sistema), mas certamente não seria pelo motivo descrito nesta resposta.
Chris Baixo
9

Isso aconteceu comigo em uma nova instalação do Ubuntu 14.04.

No meu caso, não teve nada a ver com os problemas de sysctl mencionados.

Em vez disso, o problema era que o UUID da partição de troca era diferente durante a instalação do que era após a instalação. Portanto, minha troca nunca foi ativada e minha máquina trava após algumas horas de uso.

A solução foi verificar o UUID atual da partição de swap com

sudo blkid

e, em seguida, sudo nano /etc/fstabpara substituir o valor UUID do swap incorreto pelo relatado por blkid.

Uma simples reinicialização para afetar as alterações, e pronto.

Dale Anderson
fonte
3
Muito obrigado! Eu tenho lutado com esse bug incrivelmente irritante por algo próximo de um ano agora, e tinha tentado de tudo para corrigi-lo. Por que o Linux tem esse comportamento? Parece que deveria agir como se não houvesse troca e apenas invocar o assassino do OOM. Em vez disso, parece fingir que há troca, mas falha ao trocar as coisas (porque na verdade não existe, pois está configurado incorretamente).
crazy2be
@ crazy2be Não está falhando, está tendo sucesso sem fim. Mesmo sem nenhuma troca, o Linux ainda pode paginar os programas e arquivos não modificados na memória e lê-los novamente a partir do disco.
Martin Thornton
4

Sei que esta pergunta é antiga, mas tive esse problema no Ubuntu (Chrubuntu) 14.04 em um Chromebook Acer C720. Tentei a solução de Krišjānis Nesenbergs e funcionou um pouco, mas ainda travava às vezes.

Finalmente encontrei uma solução que funcionava instalando o zram em vez de usar a troca física no SSD. Para instalá-lo, apenas segui as instruções aqui , assim:

sudo apt-get install zram-config

Posteriormente, consegui configurar o tamanho da troca do zram modificando /etc/init/zram-config.confna linha 21.

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

Substituí o 2 por 1 para fazer o tamanho do zram do mesmo tamanho que a quantidade de memória RAM que tenho. Desde que fiz isso, não tive mais congelamentos ou falta de resposta do sistema.

brismuth
fonte
zramsó é viável se você não conseguir instalar mais RAM. Se o sistema estiver muito lento ao trocar para SSD e ficar sem memória RAM sem troca, zrampoderá ajudar um pouco até você tentar fazer um pouco mais e o resultado ser o mesmo que ficar sem memória RAM sem troca.
Mikko Rantalainen
4

Nada funcionou para mim !!

Então, eu escrevi um script para monitorar o uso da memória. Primeiro, ele tentará limpar o cache da RAM se o consumo de memória aumentar um limite. Você pode configurar esse limite no script. Se o consumo de memória não estiver abaixo do limite, mesmo assim, ele começará a interromper os processos em um em ordem decrescente de consumo de memória até que o consumo de memória esteja abaixo do limite. Eu configurei para 96% por padrão. Você pode configurá-lo alterando o valor da variável RAM_USAGE_THRESHOLD no script.

Concordo que matar processos que consomem muita memória não é a solução perfeita, mas é melhor matar UM aplicativo em vez de perder todo o trabalho! o script enviará uma notificação na área de trabalho se o uso da RAM aumentar o limite. Também o notificará se matar algum processo.

#!/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)

Salve o código em um arquivo, como save_hang.py. Execute o script como:

sudo python save_hang.py

Observe que este script é compatível apenas com o Python 3 e requer a instalação do pacote tkinter. você pode instalá-lo como:

sudo apt-get install python3-tk

Espero que isto ajude...

Saim Raza
fonte
2

Meu palpite é que você definiu seu vm.swappinessvalor muito baixo, o que faz com que o kernel troque tarde demais, deixando RAM muito baixa para o sistema trabalhar.

Você pode mostrar sua configuração de swappiness atual executando:

sysctl vm.swappiness

Por padrão, isso é definido como 60. O Ubuntu Wiki recomenda configurá-lo para 10, mas fique à vontade para defini-lo com um valor mais alto. Você pode alterá-lo executando:

sudo sysctl vm.swappiness=10

Isso irá alterá-lo apenas para a sessão atual . Para torná-lo persistente, você precisa adicionar vm.swappiness = 10ao /etc/sysctl.confarquivo.

Se o seu disco estiver lento, considere comprar um novo.

Lekensteyn
fonte
Na verdade, reduzir a permutabilidade reduziu o problema (aconteceu mais raramente). Estou mantendo às 5 agora. Embora talvez tenha sido outro problema com a troca do higer, porque, quando tinha 60 anos, e eu decidi assistir a um filme ou editar um arquivo grande, um arquivo inteiro e quase um GB foram carregados na memória e, instantaneamente, o sistema começou a trocar os programas que eu estava usando ativamente e até a própria interface do usuário. O problema é que eu entendo a parte da troca, o que eu quero é matar aplicativos de usuário gananciosos em vez de congelar a máquina ao ficar sem memória RAM. (E de preferência limitar o tamanho do arquivo em cache)
Krišjānis Nesenbergs
@ Krisa: quando o sistema fica sem memória (RAM e swap), o kernel chama oom_kill, que mata os processos para economizar memória. Infelizmente, você não pode controlar os processos de destino. Para acioná-lo manualmente, pressione Alt + SysRq + F. Ao executar o dmesgcomando, você verá algumas informações (e o nome do processo + id) do processo. Acho melhor você comprar um disco novo e mais rápido. Ou atualize sua RAM.
Lekensteyn
3
O problema é que o oom_kill simplesmente não é chamado antes que o computador seja bloqueado por cerca de 30 minutos. Além disso - existe pelo menos uma maneira de saber qual processo será morto primeiro?
Krišjānis Nesenbergs
2
Eu tenho 2 GB de RAM e o disco rígido é 5400rpm. Realmente não acho que seja um sistema tão antigo que justifique meia hora de congelamento enquanto assiste a um vídeo em um monitor e navega em 20 a 30 abas no outro. Na verdade, eu ficaria muito feliz se pudesse acessar o console e interromper alguns processos - existe uma maneira de tornar a entrada do usuário e o terminal com alta prioridade para que funcione enquanto o sistema congela?
Krišjānis Nesenbergs
1
Enfim - trocar e a quantidade de RAM é um pouco offtopic. O problema é que esse sistema fica sem resposta por um longo tempo, mesmo se a troca estiver desativada, e depois disso algumas vezes ainda executa o programa (por isso consegue encontrar memória em algum lugar) e outras vezes executa oom_killer. O sistema deve ser capaz de dizer que está ficando sem memória RAM e não me deixar executar mais coisas. Portanto, existe alguma maneira de interromper esses congelamentos ou definir a prioridade da entrada do usuário tão alta que eu possa mudar para o console quando eles acontecerem e matar alguns processos por conta própria?
Krišjānis Nesenbergs
2

Estou lutando com esse problema há muito tempo, mas agora ele parece estar resolvido no meu laptop.

Se nenhuma das outras respostas funcionar para você (tentei a maioria delas), brinque com min_free_kbytes , para ter mais espaço na RAM quando o computador começar a trocar (pouco antes de atingir esse valor mínimo na RAM livre).

Tenho 16 GB de RAM, mas mais cedo ou mais tarde a memória ficou cheia e parou de responder por 10 a 30 minutos, até que algumas coisas foram trocadas.

Pelo menos para mim, definir o valor min_free_kbytes acima do recomendado torna esse processo de troca consideravelmente mais rápido.

Para 16 GB de RAM, tente o seguinte:

vm.min_free_kbytes=500000

Para definir esse valor, veja outras respostas ou apenas pesquise no Google :)

Beto Aveiga
fonte
0

Eu corro constantemente um dos meus laptops a partir de um cartão SD do Ubuntu ao vivo, com uma pequena partição ext4 de armazenamento e um arquivo de troca no disco rígido. Quando quase toda a RAM é usada e o valor de troca é muito baixo (às vezes eu prefiro manter o disco rígido completamente desligado, se possível, porque é barulhento), o desempenho do Linux tende a cair de um penhasco para mim, de modo que apenas TTY1 para matar o Firefox leva 15 minutos.

Aumentar /proc/sys/vm/vfs_cache_pressuredo padrão de 100 para um valor de 6000 parece ajudar a evitar isso. No entanto, a documentação do kernel adverte contra isso, dizendo

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.

Não tenho muita certeza dos efeitos colaterais de fazer isso, por isso tome cuidado.

Hitechcomputergeek
fonte
Você provavelmente obterá melhores resultados com vfs_cache_pressuremais de 10 (ou seja, muito menos que 100) e com configurações min_free_kbytesmais altas. Esteja avisado de que se você definir min_free_kbytesmuito alto, o OOM killer do kernel matará todos!
Mikko Rantalainen
@MikkoRantalainen Eu já subi min_free_kbytespara 262144 e observei que abaixar vfs_cache_pressuretem o efeito oposto - abaixá-lo abaixo de 100 faz com que o sistema deixe de responder muito mais rápido. Não sei por que exatamente.
Hitechcomputergeek
Em geral, o aumento vfs_cache_pressurefará com que os direntries sejam lançados antes do conteúdo do arquivo em cache e, como resultado, o desempenho geral geralmente sofrerá valores acima de 100. Se você puder descobrir as etapas de reprodução para travar / travar o sistema, iniciando com, por exemplo, o Ubuntu Live CD então os desenvolvedores do kernel podem descobrir a causa raiz. Para mim, o travamento ocorre sem nenhum aviso. Meu melhor palpite é que o kernel trava devido ao OOM antes que o OOM Killer libere RAM suficiente. Agora estou executando min_free_kbytes = 100000, admin_reserve_kbytes = 250000 e user_reserve_kbytes = 500000.
Mikko Rantalainen
(cont) Eu ainda não travei com a configuração acima, apesar de ter swappiness = 5 e vfs_cache_pressure = 20. O sistema possui 16 GB de RAM e 8 GB de swap no SSD. Outro sistema tem 32 GB de RAM e troca zero e parece ter o mesmo problema aleatoriamente - pressionar Alt + SysRq + f depois que o sistema parece lento parece ajudar, então eu acho que se o OOM Killer estivesse agindo rápido o suficiente, o sistema não travaria.
Mikko Rantalainen