Por que o Linux, por padrão, sobrecarrega a memória?

Por que o Linux, por padrão, sobrecarrega a memória?

Relacionado à pergunta do SuperUser emhttps://superuser.com/questions/200387/linux-overcommit-memoryminha pergunta é qual foi a razão pela qual eles permitiram o overcommit do padrão?

Desde 2.5.30 os valores são: 0 (padrão): como antes: adivinhe quanto excesso de comprometimento é razoável,

Responder1

Grande parte da necessidade de alocar memória demais no Linux (e nos sistemas Unix em geral) vem da necessidade de implementar a fork()chamada do sistema, que duplica o espaço de endereço do processo de chamada.

Na maioria das vezes, essa chamada de sistema é seguida por exec(), cuja combinação resulta na geração de um programa separado como filho do processo atual; nesse caso, a maior parte do espaço de endereço duplicado acabará não sendo usada.

Para tornar isso eficiente, o Linux utiliza copy-on-write para evitar a duplicação da memória da aplicação que está chamando fork(), caso em que pode evitar a necessidade de copiar todas as páginas, apenas para descartá-las logo após exec()ser chamada.

Mas no momento em que fork()é chamado, não há como saber se um exec()está chegando. É bem possível que isso esteja sendo usado para gerar filhos trabalhadores e que a reutilização do espaço de endereço do pai seja o desejado. (Essa técnica era bastante popular em daemons que usavam trabalhadores pré-bifurcados para lidar com conexões.) Nesse caso, a maioria ou pelo menos alguns dos requisitos de memória existirão para um filho bifurcado (talvez não 100% da memória do pai, mas pode-se assuma a maior parte.)

Mas sempre reservar memória para esse caso é problemático para o caso fork()+ exec(), especialmente se o pai for um processo de longa execução que reserva vários gigabytes de memória e bifurca muitos filhos. Se não fosse pelo excesso de comprometimento, você teria que reservar uma quantia totalizando os muitos gigabytes usados ​​pelo pai, e isso para cada filho bifurcado. Mas nada (ou quase nada) disso seria realmente utilizado, pois exec()liberaria essa reserva imediatamente. O resultado final é que tal carga de trabalho exigiria uma enorme quantidade de espaço de troca (para lidar com as reservas, a maior parte não seria utilizada, mas precisaria estar lá no pior dos casos) ou algo como supercomprometimento.

Embora fork()seja uma ótima ilustração deste exemplo, outras APIs no Linux/Unix também levam à necessidade de comprometimento excessivo. Por exemplo, quando malloc()é chamado (ou mais precisamente os syscalls que o implementam), nenhuma memória é realmente alocada até que seja "tocada" pelo processo, então é perfeitamente válido alocar um bloco muito grande de gigabytes e usá-lo esparsamente para que apenas alguns megabytes são realmente usados. O fato de essas APIs funcionarem dessa maneira significa que os programas exploram essas propriedades, o que significa que eles provavelmente quebrariam na ausência de supercomprometimento (a menos que você realmente tenha muita memória ou troque para desperdiçar ao fazer backup dessas reservas).

Uma discussão interessante sobre o assunto fork()pode ser encontrada emesta postagem do LWN sobre um artigo da Microsoft Research. O artigo em si é interessante, claro. Mas você pode ver como os comentários levam imediatamente ao comprometimento excessivo e aos problemas com isso.

O artigo é nomeadoUma bifurcação() na estrada.

Responder2

Acho que a razão é que nem todas as pessoas têm recursos suficientes para comprar memória, então nesses casos todos os aplicativos devem rodar corretamente, isso ajuda a rodar aplicativos com poucos recursos.

informação relacionada