Resposta curta
O pop-up "falta de memória" indica que você está ficando sem o limite da memória confirmada privada - um tipo de memória virtual. Não que você esteja ficando sem memória RAM. Não importa quanta RAM disponível você possui. Ter muita RAM disponível não permite que você exceda o limite de confirmação. O limite de confirmação é a soma da sua RAM total (em uso ou não!) Mais o tamanho atual do arquivo de paginação.
Por outro lado, o limite de consolidação "esgotado" (que é principalmente a criação do espaço de endereço virtual privado do processo) não usa necessariamente nenhuma RAM! Mas o sistema operacional não permitirá sua criação, a menos que saiba que há algum lugar para armazená-lo, se for necessário. Portanto, você pode executar o limite de confirmação sem usar toda a sua RAM ou até 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 talvez nunca seja realmente gravado! Mas ainda assim você evita os erros de "pouca memória" e "falta de memória".
Resposta Intermediária
O Windows não tem realmente uma mensagem de erro para ficar sem memória RAM. O que você está ficando sem é "limite de confirmação".
O gráfico "Sistema" nessa versão do Process Explorer não tem nome. Deve ser rotulado como "taxa de confirmação". (Na versão que tenho, chama-se "Confirmação do sistema". Melhor, mas ainda não completamente consistente.) De qualquer forma, a altura "atual" do gráfico é exibida mais abaixo na seção de texto como "Confirmação de cobrança" - " Current "e a altura máxima do gráfico representa" Commit Charge "-" Limit ".
"Confirmar cobrança" refere-se ao espaço de endereço virtual suportado pelo arquivo de paginação (se você tiver um) - em outras palavras, se ele não puder caber na RAM, o restante ficará no arquivo de paginação. (Existem outros tipos de vas que são apoiados por outros arquivos - chamados de "mapeados" - ou que precisam permanecer na RAM o tempo todo; o último é chamado de "não paginável".) O "limite de confirmação" é o máximo que a "taxa de confirmação" pode ser. É igual ao tamanho da RAM mais o tamanho do arquivo de paginação.
Você aparentemente não possui um arquivo de paginação (eu posso dizer porque o seu limite de confirmação é igual ao tamanho da RAM), então o limite de confirmação é simplesmente o tamanho da RAM.
Aparentemente, vários programas + o sistema operacional usaram quase todo o máximo possível de confirmação.
Isso não tem nada a ver diretamente com a quantidade de RAM disponível ou gratuita. Sim, você tem cerca de 4,5 GB de RAM disponível. Isso não significa que você pode exceder o limite de confirmação. A memória confirmada não usa necessariamente a RAM e não é limitada pela quantidade de RAM disponível.
Você precisa reativar o arquivo de paginação - usando isso muito comprometido, eu sugeriria um arquivo de paginação de 16 GB, porque você não deseja forçar o sistema operacional a manter muito disso na RAM e o arquivo de paginação funciona melhor se tem muito espaço livre - ou 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 sobre gerenciamento de memória do Windows Internals ...)
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 "confirmar". Isso resultará em um aumento de 100 MB na "taxa de confirmação". Mas essa "alocação" na verdade não usa nenhuma RAM! A RAM é usada apenas quando parte desse espaço de endereço virtual recém-confirmado é acessado pela primeira vez.
Como a RAM acaba sendo usada
(se houver)
O acesso pela primeira vez ao espaço recém-confirmado quase sempre seria uma gravação de memória (ler o arquivo privado recém-alocado antes de gravá-lo é quase sempre um erro de programação, pois seu conteúdo inicial é, a rigor, indefinido). Mas leia ou escreva, o resultado, a primeira vez que você toca em uma página do vas recém-alocado, é uma falha na página . Embora a palavra "falha" pareça ruim, as falhas de página são um evento completamente esperado e até 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 vou abreviar como "Mm"):
- aloque uma página física de RAM (de preferência da lista de páginas zero, mas, de qualquer forma, é proveniente do que o Windows chama de "disponível": a lista de páginas zero, livre ou em espera, nessa ordem de preferência);
- preencha uma entrada da tabela de páginas para associar a página física à página virtual; e finalmente
- ignore a exceção de falha da página.
Após o qual o código que fez a referência de memória executará novamente a instrução que causou a falha da página e, dessa vez, a referência terá êxito.
Dizemos que a página foi "invadida" 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 particular" do processo. E uma redução de uma página na memória física disponível. (Pode ser difícil perceber o último em uma máquina ocupada.)
Nota 1: Esta falha na página não envolveu nada lido no disco. Uma página nunca antes acessada de memória virtual confirmada não inicia a vida em disco; não tem lugar no disco para lê-lo a partir . É simplesmente "materializado" em uma página de RAM anteriormente disponível. Estatisticamente, de fato, a maioria das falhas de página é resolvida na RAM, para páginas compartilhadas que já estão na RAM para outros processos ou para os caches da página - as listas em espera ou modificadas ou como "exigem zero" páginas como esta.
Nota 2: Leva apenas uma página, 4096 bytes, de "Disponível". O espaço de endereço confirmado nunca tocado antes é normalmente realizado - com falha - apenas uma página de cada vez, pois cada página é "tocada" pela primeira vez. Não haveria melhoria, nem vantagem, em fazer mais de cada vez; levaria apenas n vezes. Por outro lado, quando as páginas precisam ser lidas a partir do disco, é tentada uma certa quantidade de "readahead" porque a grande maioria das vezes na leitura do disco ocorre em sobrecarga por operação, não na transferência real de dados. A quantidade "confirmada" permanece em 100 MB; o fato de uma ou mais páginas terem sido danificadas não reduz a cobrança de confirmação.
Nota 3:Vamos supor que temos 4 GB de RAM "disponível". Isso significa que poderíamos fazer referência à memória comprometida já alocada, mas nunca antes mencionada, cerca de um milhão de vezes (4 GB / 4096) antes de ficarmos sem memória RAM. Nesse ponto, se tivermos um arquivo de paginação como David Cutler e Lou Perazzoli pretendiam, algumas das páginas mencionadas na RAM há mais tempo seriam salvas no disco e 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 são armazenadas em cache e em lotes na lista de páginas modificadas para maior eficiência ee ...) Nada disso afetaria o contagem "confirmada". É relevante, porém, para o "limite de confirmação". Se não houver espaço para todos "
E continua acontecendo ...
Mas vamos supor que não fizemos mais esse milhão de referências e ainda existem cerca de 4 GB de páginas "disponíveis". Agora, suponhamos que o mesmo processo - ou outro, não importe - faça outro VirtualAlloc, desta vez com 200 MB confirmados. Novamente, esses 200 MB são adicionados à cobrança de confirmação e não removem nenhuma RAM da disponível. Simplesmente o espaço de endereço do VirtualAlloc'ating não consome 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 usar no VirtualAlloc (nem aumentar a RAM disponível).
(Bem, ok ... há um pouco de sobrecarga, no valor de uma página (paginável!) Usada para uma tabela de páginas a cada 2 MB (4 MB se você estiver em um sistema x86, não PAE) de espaço de endereço virtual alocado e existe um "descritor de endereço virtual" de algumas dezenas de bytes para cada intervalo alocado virtualmente contíguo.)
Desta forma, é possível - e comum! - usar muita "carga de confirmação" enquanto usa apenas pequenas quantidades de RAM.
Portanto, se "confirmar" o espaço de endereço virtual não usa RAM, por que tem que haver um limite?
Como a "taxa de confirmação" representa o uso futuro potencial do espaço de armazenamento. "Limite de confirmação" representa a quantidade total de armazenamento (RAM + espaço no arquivo de paginação) disponível para reter essas alocações, caso elas realmente sejam referenciadas e, portanto, precisem ser armazenadas em algum lugar.
Quando o Mm aprova uma solicitação do VirtualAlloc, é promissor - "comprometendo-se" - que todos os acessos de memória subsequentes à área alocada tenham êxito; eles podem resultar em falhas de página, mas todos poderão ser resolvidos, pois há 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 confirmação) e quanto já foi "confirmado" (a taxa de confirmação atual).
(Mas todas essas páginas ainda não foram necessariamente acessadas, portanto, não há necessariamente um armazenamento real para acompanhar a quantidade confirmada, a qualquer momento.)
Então ... Que tal "o sistema está sem memória"?
Se você tentar o VirtualAlloc e a taxa de confirmação atual mais o tamanho da alocação solicitada ultrapassar o limite de confirmação, o SO não poderá expandir o arquivo de paginação para aumentar o limite de confirmação ... você obtém o pop-up "sem memória" e o processo vê a chamada VirtualAlloc FAIL. A maioria dos programas apenas levanta as mãos e morre nesse ponto. Alguns continuarão cegamente, assumindo que a chamada foi bem-sucedida e falharão mais tarde quando tentarem fazer referência à região que pensavam ter alocado.
Mais uma vez (desculpe a repetição): não importa quanta RAM disponível você possui. O sistema operacional prometeu que a RAM ou o espaço do arquivo de paginação estará disponível quando necessário, mas essa promessa não subtrai de "Disponível". A RAM disponível é usada apenas pela vm confirmada quando é referenciada pela primeira vez, e é isso que faz com que ela seja "defeituosa" ... ou seja, realizada na memória física. E simplesmente confirmar (= alocar) memória virtual não faz isso. Ele ocupa apenas espaço de endereço virtual gratuito e o torna utilizável.
Mas na "falta de memória" caso houve uma solicitação de alocação de memória confirmada, eo OS acrescentou a atual carga comprometida com o tamanho do pedido neew ... e descobriu que o total é mais do que o limite cometer. Portanto, se o sistema operacional aprovasse esse novo e todo esse espaço fosse referenciado depois disso, não haveria lugares reais (RAM + arquivo de paginação) para armazenar tudo.
O sistema operacional não permitirá isso. Não permitirá que mais vas sejam alocados do que há espaço para mantê-lo no pior dos casos - mesmo que tudo seja "reprovado". Esse é o objetivo do "limite de confirmação".
Eu digo três vezes, eu digo três vezes, eu digo três vezes: A quantidade de RAM "disponível" não importa. Que o espaço virtual confirmado ainda não esteja usando todo esse espaço de armazenamento, não importa. O Windows não pode "confirmar" a alocação virtual, a menos que '' possa '' ser danificado 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 por "confirmação de carga" e não é limitado pelo "limite de confirmação". Isso ocorre porque ele vem com sua própria área de armazenamento, os arquivos que são "mapeados" para ele. O único limite para o vas "mapeado" é a quantidade de espaço em disco que você tem para os arquivos mapeados e a quantidade de vas livre em seu processo para mapeá-los.
Mas quando olho para o sistema, ainda não estou no limite de confirmação?
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 confirmação restante e que algum programa tenha tentado o VirtualAlloc 600 MB. A tentativa falha. Então você olha para o sistema e diz "O quê? Ainda há 500 MB!" De fato, pode haver muito mais até então, porque o processo em questão provavelmente já foi completamente nesse ponto; portanto, toda a sua memória confirmada alocada anteriormente foi liberada.
O problema é que você não pode olhar para trás no tempo e ver qual era a cobrança de confirmação no momento em que foi feita a tentativa de alocação. E você também não sabe quanto espaço a tentativa teve. 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 ela funcionasse.
Eu vi "o sistema está com pouca memória". O que é isso?
Se, no caso acima, o SO PODE expandir o arquivo de paginação (ou seja, você o deixa na configuração padrão "gerenciado pelo sistema" ou o gerencia, 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 antecipado 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 é uma coisa boa? A expansão do arquivo de paginação é má !!!
Não é não. Veja, o sistema operacional não "expande" realmente o arquivo existente. Apenas aloca uma nova extensão. O efeito é semelhante a 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 assim. Como a maioria das E / S de arquivo de paginação está em blocos relativamente pequenos em comparação com o tamanho do arquivo de paginação, as chances de que uma determinada transferência ultrapasse um limite de extensão são realmente muito raras, portanto a fragmentação não prejudica muito, a menos que seja realmente excessiva.
Por fim, depois que todos os processos com espaço "confirmado" na extensão são encerrados (no encerramento do SO, se não antes), as extensões são liberadas silenciosamente e o arquivo de paginação volta ao tamanho e à alocação anteriores - se era contíguo antes, é tão 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, o sistema não "expandirá e contratará constantemente o arquivo de paginação", como costuma ser reivindicado, por isso não custará nada . E se você precisar, ele o salvará de aplicativos 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 constantemente expandirá e contrairá o arquivo de paginação, e isso resultará em fragmentação do arquivo de paginação até você desfragmentá-lo.
Eles estão errados.
Se você nunca viu o pop-up "com pouca memória" (ou, em versões anteriores, "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 do arquivo de paginação inicial é muito pequeno. (Gosto de configurá-lo para cerca de 4x o uso máximo observado; ou seja, o contador perfmon "% pagefile use peak" deve estar abaixo de 25%. Motivo: o espaço no 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 ...
Alguém pode argumentar que o sistema operacional deve deixar a alocação acontecer e deixar as referências falharem se não houver RAM disponível para resolver as falhas da página. Em outras palavras, acima de onde descrevemos como a falha da página inicial funciona, e se a "alocação de uma página física disponível da RAM" (etapa 1) não pudesse ser feita porque não havia nenhuma disponível e não havia lugar saiu para paginar alguma coisa para disponibilizar alguma?
O pager não conseguiria resolver a falha da página. Teria que permitir que a exceção (a falha da página) fosse relatada de volta ao encadeamento com falha, provavelmente alterado para 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ê ficar sem o limite de confirmação, e é inteiramente 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 uma chance de salvar seu trabalho até esse ponto e depois encerrar o programa "normalmente"). (Programadores: você verifica se há um ponteiro NULL retornado de malloc, new, etc., sim? Então por que não faria isso?)
Mas os programadores não devem 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 o espaço de endereçamento mapeado, aliás.) Mas é isso que poderia acontecer se a filosofia "permitir a alocação supercomprometida, falhar a referência de memória" 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 funcionar , assim como adição e subtração. A única maneira de relatar essas falhas seria como exceções. Portanto, para lidar com eles, o programador teria que agrupar o programa inteiro em um manipulador de exceções. (tente ... pegar e tudo mais.)
Isso pode ser feito ... Mas seria difícil para o manipulador saber "fazer a coisa certa" em resposta a essas exceções, pois haveria muitos, muitos pontos no código onde eles poderiam surgir. (Especificamente, eles podem surgir a cada referência de memória à memória do VirtualAlloc, à memória alocada com malloc ou novo ... e a todas as variáveis locais, já que a pilha também é VirtualAlloc.)
Em resumo, fazer com que o programa falhe normalmente nesses casos seria muito difícil.
Por outro lado, é muito fácil verificar se um ponteiro NULL retorna do VirtualAlloc (ou malloc ou novo, por sinal, embora não sejam exatamente a mesma coisa) e depois fazer algo razoável ... como não tentar ir e faça o que for para o qual o programa precisava desse espaço virtual. E talvez pergunte ao usuário se ele deseja salvar seu trabalho até agora, se houver. (É verdade que muitos aplicativos não se incomodam em fazer isso.)
Outros usuários de confirmação
Aliás, o "limite de confirmação" não é reduzido pelas várias alocações do sistema operacional, como pool paginado e não paginado, lista PFN, etc .; estes são cobrados apenas para confirmar a cobrança à medida que ocorrem. Tampouco a carga de confirmação ou o limite de confirmação são afetados pela RAM de vídeo ou pelo tamanho da "janela" da RAM de vídeo.
Teste você mesmo
Você pode demonstrar tudo isso com a ferramenta testlimit no site da SysInternals. A opção -m alocará o 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 taxa de confirmação aumente e a RAM disponível diminua.
Referências
Windows Internals de Russinovich, Solomon e Ionescu. Existem até demonstrações que permitem provar todos esses pontos usando a ferramenta testlimit. No entanto, devo advertir que, se você acha que isso foi longo, esteja avisado: o capítulo Mm sozinho tem 200 páginas; o acima é uma versão extremamente simplificada. (Consulte também a seção "Agradecimentos" na Introdução.)
Consulte também a documentação do MSDN VirtualAlloc