¿Por qué Linux, de forma predeterminada, compromete excesivamente la memoria?

¿Por qué Linux, de forma predeterminada, compromete excesivamente la memoria?

Relacionado con la pregunta de Superusuario enhttps://superuser.com/questions/200387/linux-overcommit-memoryMi pregunta es ¿cuál fue la razón por la que permitieron la sobrecompromiso del valor predeterminado?

Desde 2.5.30 los valores son: 0 (predeterminado): como antes: adivine cuánto compromiso excesivo es razonable,

Respuesta1

Gran parte de la necesidad de comprometer excesivamente la memoria en Linux (y en los sistemas Unix en general) proviene de la necesidad de implementar la fork()llamada al sistema, que duplica el espacio de direcciones del proceso de llamada.

La mayoría de las veces, esta llamada al sistema va seguida de exec(), cuya combinación genera un programa separado como hijo del proceso actual, en cuyo caso la mayor parte del espacio de direcciones duplicadas terminará sin usarse.

Para hacerlo eficiente, Linux usa copia en escritura para evitar duplicar la memoria de la aplicación que llama fork(), en cuyo caso puede evitar tener que copiar todas las páginas, solo para descartarlas poco después de exec()ser llamada.

Pero en el momento en fork()que se llama, no hay forma de saber si exec()llegará. Es muy posible que esto se esté utilizando para generar hijos trabajadores y que lo que se desea sea reutilizar el espacio de direcciones del padre. (Esta técnica era bastante popular en demonios que usaban trabajadores previamente bifurcados para manejar conexiones). En cuyo caso, la mayoría o al menos algunos de los requisitos de memoria existirán para un hijo bifurcado (tal vez no el 100% de la memoria del padre, pero uno podría asumir la mayor parte.)

Pero reservar siempre memoria para ese caso es problemático para el caso fork()+ exec(), especialmente si el padre es un proceso de larga duración que reserva varios gigabytes de memoria y bifurca a muchos hijos. Si no fuera por un compromiso excesivo, tendría que reservar una cantidad total de los muchos gigabytes utilizados por el padre, y eso para cada hijo bifurcado. Pero nada (o casi nada) de eso se usaría realmente, ya que exec()eliminaría esa reserva de inmediato. El resultado final es que dicha carga de trabajo requeriría una enorme cantidad de espacio de intercambio (para hacer frente a las reservas, la mayor parte no se utilizaría, pero tendría que estar allí en el peor de los casos) o algo así como un compromiso excesivo.

Si bien fork()es una gran ilustración de este ejemplo, otras API en Linux/Unix también generan la necesidad de comprometerse demasiado. Por ejemplo, cuando malloc()se llama (o más precisamente las llamadas al sistema que lo implementan), en realidad no se asigna memoria hasta que el proceso la "toca", por lo que es perfectamente válido asignar un bloque muy grande de gigabytes y usarlo escasamente para que solo en realidad se utilizan unos pocos megabytes. El hecho de que estas API funcionen de esa manera significa que los programas explotan esas propiedades, lo que significa que lo más probable es que se rompan en ausencia de un compromiso excesivo (a menos que realmente tenga mucha memoria o se desperdicie respaldo al respaldar estas reservas).

fork()Se puede encontrar una discusión interesante sobre el tema enesta publicación de LWN sobre un artículo de Microsoft Research. El artículo en sí es interesante, por supuesto. Pero puedes ver cómo los comentarios se convierten inmediatamente en un compromiso excesivo y los problemas que conlleva.

El artículo se llamaUna bifurcación() en el camino.

Respuesta2

Creo que la razón es que no todas las personas tienen suficientes recursos para comprar memoria, por lo que en tales casos todas las aplicaciones deben ejecutarse correctamente, lo que ayuda a ejecutar aplicaciones con pocos recursos.

información relacionada