Resposta curta

Resposta curta

Captura de tela das informações do sistema do Process Explorer

Estas informações do sistema são do Process Explorer. Ainda há memória física disponível, mas o sistema quase não mostra mais RAM.

O Gerenciador de Tarefas também mostra que cerca de 74% do total de RAM é usado.

Desde a instalação do Windows 8.1, o computador tinha 4+8=12 GB de RAM. Eu atualizei mudando o módulo de 4 GB para um módulo de 8 GB. Esse poderia ser o problema? Ou esse comportamento é normal e eu simplesmente entendi mal o significado da memória física disponível?

Responder1

Resposta curta

O pop-up "sem memória" indica que você está esgotando o limite deprivado comprometidomemória – um tipo de memória virtual. Não que você esteja ficando sem RAM (memória física). Não importa o quantodisponívelRAM você tem. Ter muita RAM disponível não permite exceder o limite de confirmação. O limite de commit é a soma do seu totalRAM (em uso ou não!) mais o tamanho atual do arquivo de paginação.

Por outro lado, o que "usa" o limite de commit (que é principalmente a criação de espaço de endereço virtual privado do processo) não usa necessariamente RAM! Mas o sistema operacional não permitirá sua criação, a menos que saiba que há algum lugar para armazená-lo, caso seja necessário. Assim, você pode atingir o limite de commit sem usar toda a sua RAM, ou mesmo a maior parte da sua RAM.

É por isso que você não deve executar sem um arquivo de paginação. Observe que o arquivo de paginação pode nunca ser gravado! Mas ainda permitirá que você evite os erros de “pouca memória” e “falta de memória”.

Resposta intermediária

Na verdade, o Windows não apresenta uma mensagem de erro por falta de RAM. O que você está acabando é o "limite de confirmação".

O gráfico "Sistema" nessa versão do Process Explorer tem um nome inadequado. Deve ser rotulado como "commit charge". (Na versão que tenho é chamado de "System commit". Melhor, mas ainda não completamente consistente.) Em qualquer caso, a altura "atual" do gráfico é o que aparece mais abaixo na seção de texto como "Commit Charge" - " Atual", e a altura máxima do gráfico representa "Commit Charge" - "Limit".

"Cobrança de confirmação" refere-se ao espaço de endereço virtual que é apoiado pelo arquivo de paginação (se você tiver um) - em outras palavras, se não caber tudo na RAM, o restante vai para o arquivo de paginação. (Existem outros tipos de vas que são apoiados por outros arquivos - chamados de vas "mapeados" - ou que devem permanecer na RAM o tempo todo; o último é chamado de "não paginável".) O "limite de confirmação" é o máximo que a "carga de confirmação" pode ser. É igual ao tamanho da RAM mais o tamanho do arquivo de paginação.

Aparentemente, você não tem nenhum arquivo de paginação (posso dizer porque o limite de commit é igual ao tamanho da RAM), então o limite de commit é simplesmente o tamanho da RAM.

Aparentemente, vários programas e o sistema operacional usaram quase todo o commit máximo possível.

Isso não tem nada a ver diretamente com a quantidade de RAM disponível ou livre. Sim, você tem cerca de 4,5 GB de RAM disponíveis. Isso não significa que você pode exceder o limite de commit. A memória comprometida não usa necessariamente RAM e não é limitada pela quantidade de RAM disponível.

Você precisa reativar o arquivo de paginação - usando tanto commit, eu sugeriria um arquivo de paginação de 16 GB, porque você não quer forçar o sistema operacional a manter tanto desse material na RAM, e o arquivo de paginação funciona melhor se for tem muito espaço livre - ou então adicione mais RAM. Muito mais. Para um bom desempenho, você precisa ter bastante espaço na RAM para código e outras coisas que não são suportadas pelo arquivo de paginação (mas podem ser paginadas para outros arquivos).

Resposta muito longa

(mas ainda muito mais curto que o capítulo de gerenciamento de memória doInternos do Windows...)

Suponha que um programa aloque 100 MB de memória virtual privada do processo. Isso é feito com uma chamada do VirtualAlloc com a opção “commit”. Isso resultará em um aumento de 100 MB na "taxa de confirmação". Mas essa "alocação" na verdade não usa RAM! RAM é usada apenas quando alguns dos recém-comprometidosespaço de endereço virtualé acessado pela primeira vez.

Como a RAM eventualmente é usada

(se isso acontecer)

O primeiro acesso ao espaço recém-comprometido seria quase sempre uma gravação na memória (ler um vas privado recém-alocado antes de gravá-lo é quase sempre um erro de programação, uma vez que seu conteúdo inicial é, estritamente falando, indefinido). Mas ao ler ou escrever, o resultado, na primeira vez que você toca em uma página de vas recém-alocada, é umfalha de página. Embora a palavra "falha" pareça ruim, as falhas de página são um evento completamente esperado e até mesmo necessário em um sistema operacional de memória virtual.

Em resposta a esse tipo específico de falha de página, o pager (parte do gerenciador de memória do sistema operacional, que às vezes abreviarei como "Mm") irá:

  1. alocar uma página física de RAM (de preferência da lista de páginas zero, mas em qualquer caso, vem do que o Windows chama de "disponível": a lista de páginas zero, livres ou em espera, nessa ordem de preferência);
  2. preencha umentrada da tabela de páginasassociar a página física à página virtual; e finalmente
  3. descartar a exceção de falha de página.

Depois disso, o código que fez a referência à memória executará novamente a instrução que gerou a falha de página e, desta vez, a referência será bem-sucedida.

Dizemos que a página sofreu uma "falha" no conjunto de trabalho do processo e na RAM. No Gerenciador de Tarefas, isso aparecerá como um aumento de uma página (4 KB) no “conjunto de trabalho privado” do processo. E uma redução de uma página na memória física disponível. (Este último pode ser difícil de perceber em uma máquina ocupada.)

Nota 1:Esta falha de página não envolveu nada lido do disco. Uma página de memória virtual comprometida nunca antes acessada não começa a vida no disco; não tem lugar no disco para lê-lode. Ele é simplesmente "materializado" em uma página de RAM previamente disponível. Estatisticamente, de fato, a maioria das falhas de página são resolvidas na RAM, seja para páginas compartilhadas que já estão na RAM para outros processos, ou para os caches de páginas - as listas de espera ou modificadas, ou como páginas de "demanda zero" como esta.

Nota 2:Isso ocupa apenas uma página, 4.096 bytes, de "Disponível". O espaço de endereço confirmado nunca tocado antes é normalmente realizado - com falha - apenas uma página por vez, à medida que cada página é "tocada" pela primeira vez. Não haveria melhoria nem vantagem em fazer mais de cada vez; levaria n vezes mais tempo. Por outro lado, quando as páginas precisam ser lidas do disco, uma certa quantidade de "readahead" é ​​tentada porque a grande maioria do tempo de leitura do disco ocorre em sobrecarga por operação, e não na transferência real de dados. O valor “comprometido” permanece em 100 MB; o fato de uma ou mais páginas terem sofrido falhas não reduz a taxa de confirmação.

Nota 3:Suponhamos que temos 4 GB de RAM “disponíveis”. Isso significa que poderíamos fazer referência à memória comprometida já alocada, mas nunca antes referenciada, cerca de um milhão de vezes mais (4 GB/4096) antes de ficarmos sem RAM. Nesse ponto, se tivéssemos um arquivo de paginação como David Cutler e Lou Perazzoli pretendiam, algumas das páginas referenciadas há mais tempo na RAM seriam salvas no disco e então disponibilizadas para uso na resolução dessas falhas de página mais recentes. (Na verdade, o sistema operacional iniciaria métodos de recuperação de RAM, como "corte do conjunto de trabalho", antes disso, e as gravações reais no arquivo de paginação seriam armazenadas em cache e em lote na lista de páginas modificadas para eficiência, e e...) Nada disso afetaria o contagem de "comprometidos". É relevante, porém, para o "limite de confirmação". Se não houver espaço para toda a memória "comprometida" na RAM, o excesso poderá ser mantido no arquivo de paginação. Assim, o tamanho do arquivo de paginação contribui para o "limite de confirmação".

E isso continua acontecendo...

Mas vamos supor que não tenhamos feito mais esses milhões de referências e ainda haja cerca de 4 GB de páginas “disponíveis”. Agora vamos supor que o mesmo processo - ou outro, não importa - faça outro VirtualAlloc, desta vez com, digamos, 200 MB comprometidos. Novamente, esses 200 MB são adicionados à taxa de confirmação e não remove nenhuma RAM disponível. Simplesmente VirtualAlloc'ating espaço de endereço não usa uma quantidade correspondente de RAM, e ter pouca RAM "disponível" não limita a quantidade de espaço de endereço que você pode VirtualAlloc (nem ter muita RAM disponível aumenta-a).

(Bem, ok... há um pouquinho de sobrecarga, totalizando uma página (paginável!) que é usada para uma tabela de páginas para cada 2 MB (4 MB se você estiver em um sistema x86, não-PAE) de espaço de endereço virtual alocado e há um "descritor de endereço virtual" de algumas dezenas de bytes para cada intervalo alocado virtualmente contíguo.)

Dessa forma é possível – e comum! - consumir muita "carga de confirmação" usando apenas pequenas quantidades de RAM.

Então, se a "confirmação" do espaço de endereço virtual não consome RAM, por que precisa haver um limite?

Porque a "taxa de compromisso" representa potencialfuturoutilização do espaço de armazenamento. "Limite de confirmação" representa a quantidade total de armazenamento (RAM + espaço de arquivo de paginação) disponível para armazenar tais alocações,caso eles realmente sejam referenciados e, portanto, precisem ser armazenados em algum lugar.

Quando o Mm aprova uma solicitação do VirtualAlloc, ele promete - "assumindo um compromisso" - que todos os acessos subsequentes à memória à área alocada serão bem-sucedidos; podem resultar em falhas de página, mas todas as falhas poderão ser resolvidas, pois EXISTE armazenamento adequado para manter o conteúdo de todas essas páginas, seja na RAM ou no arquivo de paginação. O Mm sabe disso porque sabe quanto espaço de armazenamento existe (o limite de commit) e quanto já foi "comprometido" (a cobrança de commit atual).

(Mas todas essas páginas ainda não foram necessariamente acessadas, portanto não há necessariamente um valor real de armazenamento para acompanhar o valor comprometido, em um determinado momento.)

Então... E quanto a "o sistema está sem memória"?

Se você tentar o VirtualAlloc e a cobrança de commit atual mais o tamanho de alocação solicitado levariam você além do limite de commit, E o sistema operacional não pode expandir o arquivo de paginação para aumentar o limite de commit... você obterá o pop-up "sem memória" ativado e o processo vê a chamada do VirtualAlloc FAIL. A maioria dos programas simplesmente desistirá e morrerá nesse ponto. Alguns continuarão cegamente, presumindo que a chamada foi bem-sucedida, e falharão mais tarde, quando tentarem fazer referência à região que pensavam ter alocado.

Novamente (desculpe pela repetição): não importa quanta RAM disponível você tenha. O sistema operacional prometeu que a RAM ou espaço do arquivo de paginaçãovaiesteja disponível quando for necessário, mas essa promessa não subtrai "Disponível". A RAM disponível só é usada pela VM comprometida quando éreferenciadopela primeira vez, que é o que faz com que seja "defeituoso"... isto é, realizado na memória física. E simplesmente comprometer (= alocar) memória virtual não faz isso. Ele ocupa apenas espaço de endereço virtual livre e torna-o utilizável em espaço de endereço virtual.

Mas no caso de "falta de memória", houve uma solicitação de alocação para memória comprometida, e o sistema operacional adicionou a taxa de confirmação atual ao tamanho desta nova solicitação... e descobriu que o total émaisdo que o limite de commit. Então, se o sistema operacional aprovou este novo,etodo esse espaço fosse referenciado depois disso, não haveria nenhum lugar real (RAM + arquivo de paginação) para armazenar tudo.

O sistema operacional não permitirá isso. Ele não permitirá que mais vasos sejam alocados do que o espaço disponível para mantê-los, na pior das hipóteses - mesmo que tudo fique "defeituoso". Esse é o propósito do "limite de commit".

Eu te digo três vezes, eu te digo três vezes, eu te digo três vezes:A quantidade de RAM “disponível” não importa. Não importa que o espaço virtual comprometido ainda não esteja usando todo esse espaço de armazenamento. O Windows não pode "comprometer-se" com a alocação virtual, a menos que "possa" sofrer falhas no futuro.

Observe que existe outro tipo de vas chamado "mapeado", usado principalmente para código e para acesso a grandes arquivos de dados, mas não é cobrado para "commit charge" e não é limitado pelo "commit limit". Isso porque ele vem com uma área de armazenamento própria, os arquivos que são “mapeados” para ele. O único limite para vasos "mapeados" é a quantidade de espaço em disco que você tem para os arquivos mapeados e a quantidade de vasos livres em seu processo para mapeá-los.

Mas quando olho para o sistema, ainda não cheguei ao limite de commits?

Isso é basicamente um problema de medição e manutenção de registros. Você está olhando para o sistema depois que uma chamada do VirtualAlloc já foi tentada e falhou.

Suponha que você tenha apenas 500 MB de limite de commit restantes e algum programa tenha tentado usar 600 MB no VirtualAlloc. A tentativa falha. Aí você olha para o sistema e diz "O quê? Ainda restam 500 MB!" Na verdade, pode haver muito mais sobrando até então, porque o processo em questão provavelmente já terá desaparecido completamente nesse ponto, então TODA a sua memória comprometida anteriormente alocada foi liberada.

O problema é que você não pode olhar para trás no tempo e ver quanto custa o commit.erano momento em que a tentativa de alocação foi feita. E você também não sabe quanto espaço foi necessário para a tentativa. Portanto, você não pode ver definitivamente por que a tentativa falhou ou quanto mais "limite de confirmação" seria necessário para permitir que funcionasse.

Eu vi "o sistema éacabandona memória". O que é isso?

Se no caso acima o sistema operacional PODE expandir o arquivo de paginação (ou seja, você o deixa na configuração padrão "gerenciado pelo sistema" ou gerencia-o, mas define o máximo para maior que o inicial, E há espaço livre em disco suficiente), e essa expansão aumenta o limite de confirmação o suficiente para permitir que a chamada do VirtualAlloc seja bem-sucedida, então... o Mm expande o arquivo de paginação e a chamada do VirtualAlloc é bem-sucedida.

E é aí que você vê "o sistema está com pouca memória". Esse é um aviso prévio de que, se as coisas continuarem sem mitigação, você provavelmente verá em breve um aviso de “falta de memória”. É hora de fechar alguns aplicativos. Eu começaria com as janelas do seu navegador.

E você acha que isso é bom? A expansão do arquivo de paginação é má!!!

Não, não é. Veja, o sistema operacional realmente não "expande" o arquivo existente. Apenas aloca uma nova extensão. O efeito é muito parecido com qualquer outro arquivo não contíguo. O conteúdo antigo do arquivo de paginação permanece exatamente onde está; eles não precisam ser copiados para um novo local ou algo parecido. Como a maior parte do IO do arquivo de paginação está em pedaços relativamente pequenos em comparação com o tamanho do arquivo de paginação, as chances de qualquer transferência cruzar um limite de extensão são realmente muito raras, portanto a fragmentação não prejudica muito, a menos que seja realmente excessiva.

Finalmente, uma vez que todos os processos que "comprometeram" espaço na extensão tenham sido encerrados (no desligamento do sistema operacional, se não antes), as extensões serão liberadas silenciosamente e o arquivo de paginação retornará ao seu tamanho e alocação anteriores - se era contíguo antes, ele é assim de novo.

Permitir a expansão do arquivo de paginação, portanto, atua como uma rede de segurança totalmente gratuita: se você permitir, mas o sistema nunca precisar dela, o sistema não "expandirá e contrairá constantemente o arquivo de paginação", como costuma ser afirmado, portanto custaránada. E se você precisar dele, ele evitará que os aplicativos travem com erros de “falta de memória virtual”.

Mas mas mas...

Eu li em dezenas de sites que, se você permitir a expansão do arquivo de paginação, o Windows expandirá e contrairá constantemente o arquivo de paginação, e isso resultará na fragmentação do arquivo de paginação até que você o desfragmente.

Eles estão simplesmente errados.

Se você nunca viu o pop-up "com pouca memória" (ou, em versões mais antigas, "com pouca memória virtual"), o sistema operacional nunca expandiu seu arquivo de paginação.

Se você vir esse pop-up, isso indica que o tamanho inicial do arquivo de paginação é muito pequeno. (Gosto de configurá-lo para cerca de 4x o uso máximo observado; ou seja, o contador de perfmon "% pico de uso do arquivo de paginação" deve estar abaixo de 25%. Motivo: o espaço do arquivo de paginação é gerenciado como qualquer outro heap e funciona melhor com muito espaço livre para jogar.)

Mas por que eles simplesmente não...

Pode-se argumentar que o sistema operacional deveria apenas deixar a alocação acontecer e depois deixar oreferênciasfalhará se não houver RAM disponível para resolver as falhas de página. Em outras palavras, acima, onde descrevemos como funciona a falha de página inicial, e se a "alocação de uma página física disponível de RAM" (etapa 1) não pudesse ser feita porque não havia nenhuma disponível,enão havia mais lugar para paginar nada e disponibilizá-lo?

Então o pager não conseguiria resolver a falha de pager. Teria que permitir que a exceção (a falha de página) fosse reportada ao thread com falha, provavelmente alterada para algum outro código de exceção.

A filosofia de design é que o VirtualAlloc retornará zero (tecnicamente um ponteiro NULL) em vez de um endereço se você ultrapassar o limite de confirmação, e é totalmente razoável esperar que o programador saiba que uma chamada do VirtualAlloc pode falhar. Portanto, espera-se que os programadores verifiquem esse caso e façam algo razoável em resposta (como dar a você a chance de salvar seu trabalho até esse ponto e, em seguida, encerrar o programa "normalmente"). (Programadores: você verifica se há um retorno de ponteiro NULL de malloc, new, etc., sim? Então por que não faria isso?)

Mas os programadores não deveriam esperar que uma simples referência de memória como

i = 0;             // initialize loop counter

pode falhar - não se estiver em uma região de espaço de endereço confirmado com êxito. (Ou espaço de endereço mapeado, nesse caso.) Mas isso é o que poderia acontecer se a filosofia "permitir a alocação supercomprometida, deixar a referência de memória falhar" fosse seguida.

Infelizmente, uma referência de memória como a da linha de código acima simplesmente não possui uma maneira conveniente de retornar um status ruim! Eles deveriam apenastrabalhar, assim como adição e subtração. A única maneira de relatar tais falhas seria como exceções. Portanto, para lidar com eles, o programador teria que agrupar todo o programa em um manipulador de exceções. (tente... pegar e tudo mais.)

Isso pode ser feito... Mas seria difícil para o manipulador saber como "fazer a coisa certa" em resposta a essas exceções, já que haveria muitos, muitos pontos no código onde elas poderiam surgir. (Especificamente, eles podem surgir emtodoreferência de memória para a memória VirtualAlloc, para a memória alocada com malloc ou new... e para todas as variáveis ​​locais também, já que a pilha também é VirtualAlloc.)

Em suma, seria muito difícil fazer com que o programa falhasse normalmente nestes casos.

Por outro lado, é muito fácil verificar se há um retorno de ponteiro NULL do VirtualAlloc (ou malloc ou new, nesse caso, embora não sejam exatamente a mesma coisa) e então fazer algo razoável... como não tentar ir e faça tudo o que o programa precisava desse espaço virtual. E talvez pergunte ao usuário se ele deseja salvar o trabalho até agora, se houver. (É verdade que muitos aplicativos não se preocupam em fazer nem isso.)

Outros usuários do commit

Aliás, o "limite de confirmação" não é reduzido pelas diversas alocações do sistema operacional, como pool paginado e não paginado, lista PFN, etc.; estes são apenas cobrados para cometer cobranças à medida que acontecem. Nem a carga de confirmação ou o limite de confirmação são afetados pela RAM de vídeo, ou mesmo pelo tamanho da "janela" da RAM de vídeo.

Teste você mesmo

Você pode demonstrar tudo isso com a ferramenta testlimit do site SysInternals. A opção -m alocará espaço de endereço confirmado, mas não o "tocará", portanto não causará alocação de RAM. Enquanto a opção -d alocará e também fará referência às páginas, fazendo com que a carga de commit aumente e a RAM disponível diminua.

Referências

Internos do Windowspor Russinovich, Solomon e Ionescu. Existem até demonstrações que permitem provar todos esses pontos usando a ferramenta testlimit. Porém, devo avisar que se você acha que isso foi longo, esteja avisado: só o capítulo Mm tem 200 páginas; o acima é uma versão EXTREMAMENTE simplificada. (Por favor, dê uma olhada também na seção "Agradecimentos" na Introdução.)

Veja tambémDocumentação do MSDN VirtualAlloc

Responder2

Talvez para somara brilhante resposta aceita:

O Windows e a maioria dos programas assumem que podem comprometer tanta memória (virtual) quanto necessária. Esta é uma das grandes razões pelas quais não se deve desabilitar o arquivo de paginação, veja a propostafato 2.2emminha pergunta de superusuário.

Eu também linko paraesta brilhante resposta serverfaultaí, o que deixa claro como funciona o arquivo de paginação:

Muitas pessoas parecem presumir que o Windows envia dados para o arquivo de paginação sob demanda. EX: algo precisa de muita memória e não há RAM suficiente para suprir a necessidade, então o Windows começa a gravar dados loucamente da RAM no disco neste último minuto, para poder liberar RAM para as novas demandas.

Isso está incorreto. Há mais coisas acontecendo nos bastidores. De modo geral, o Windows mantém umloja de apoio, o que significa que ele deseja ver tudo o que está na memória também em algum lugar do disco. Agora, quando surge algo e exige muita memória, o Windows pode limpar a RAM muito rapidamente, porque esses dados sãono disco, pronto para ser paginado de volta na RAM, se necessário. Portanto, pode-se dizer que muito do que está no arquivo de paginação também está na RAM; os dados forampreventivamentecolocado no arquivo de paginação para acelerar novas demandas de alocação de memória.

Leitura adicionalé fornecidoaqui

informação relacionada