java - xmn - Un simple "Hola mundo" necesita memoria virtual 10G en una máquina de 64 bits frente a 1G a 32 bits?
parametros xms xmx java (7)
Esta no es la cantidad de memoria física que la aplicación está usando en realidad. Una memoria virtual utilizada por todos los procesos puede ser órdenes de magnitud más que la cantidad de RAM física en la máquina, sin ningún problema obvio.
Al ejecutar un programa Java simple en nuestra máquina de producción, noté que este programa consume más 10G virt. Sé que la memoria virtual no es tan relevante, pero al menos me gustaría entender por qué es necesaria.
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
try {
Thread.sleep(10000);
} catch(InterruptedException e) {
/* ignored */
}
}
}
Aquí está lo que dice la top
cuando ejecuto ese pequeño programa:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18764 myuser 20 0 10.2g 20m 8128 S 1.7 0.1 0:00.05 java
¿Alguien sabe por qué ocurre esto?
uname -a dice:
Linux m4fxhpsrm1dg 2.6.32-358.18.1.el6.x86_64 #1 SMP Fri Aug 2 17:04:38 EDT 2013 x86_64 x86_64 x86_64 GNU/Linux
En una máquina anterior de 32 bits y Linux, el mismo programa consume solo 1G virt. La máquina vieja tiene 4 GB de RAM, la nueva de 32 GB.
Imagina que estás en el negocio de almacenamiento de documentos. Tiene una pequeña instalación en el medio de la ciudad que almacena cajas de papeles, y un almacén mucho más grande fuera de la ciudad con 1000 veces el espacio. Cada caja tiene una etiqueta que identifica su contenido.
La instalación en la ciudad es memoria principal. El almacén es espacio en disco.
Una asignación de memoria virtual de 10 GB para un nuevo proceso no significa encontrar espacio para 10 mil millones de cajas para un nuevo cliente. Significa imprimir 10 mil millones de etiquetas para cajas con números de identificación contiguos.
La memoria virtual realmente no te importa.
La diferencia básica entre 32 bits y 64 bits es que el espacio de direcciones en 64 bits es increíblemente grande. Si 10 GiB parece mucho para usted, tenga en cuenta que .NET en 64 bits puede usar TiBs de memoria como este. Sin embargo, en 32 bits, .NET es mucho más conservador (y también lo es JVM), el espacio de direcciones es 4 GiB en total , eso no es mucho.
Pero es irrelevante, no importa. Es simplemente una cosa que simplifica enormemente la programación, y no tiene ningún efecto negativo en el sistema operativo host en absoluto. Crea un espacio de direcciones continuo para que la VM lo use, lo que significa que no tiene que fragmentar el montón (o peor, la pila, donde es más o menos imposible, pero esos tienden a ser solo un MiB) como puedes requerir más memoria "real". Cuando finalmente se compromete la memoria virtual, se vuelve un poco más real: en ese punto, más o menos tiene que estar respaldada por algún almacenamiento de datos, ya sea el archivo de página (intercambio) o la memoria RAM física.
El punto es que la ubicación física de la memoria no es necesariamente continua, pero eso se hace fuera de su alcance, y el mapeo es generalmente muy rápido. Por otro lado, tener que, por ejemplo, indexar una matriz, que en realidad está fragmentada en 10 bloques de memoria de direcciones virtuales diferentes, eso es (completamente innecesario) el trabajo.
Así que ahí lo tienen: la memoria virtual es casi gratuita en 64 bits. El enfoque básico es "si está allí, úsala". No está limitando las otras aplicaciones, y le ahorrará bastante trabajo si realmente termina usándolo. Pero hasta que llegue ese punto, solo tienes una reserva. No se traduce a ninguna memoria física en absoluto. No pagas por los amigos que podrían venir esta noche y te sientas en tu mesa, pero aún tienes el espacio para que se sienten si vienen, y solo cuando finalmente vienen te cobran.
Consulte esta pregunta para obtener más información sobre la forma en que se comporta Java en diferentes máquinas y con diferentes versiones: ¿Cuál es el tamaño de almacenamiento dinámico máximo predeterminado para la JVM de Sun desde Java SE 6? El tamaño de montón máximo también determina la cantidad de memoria virtual reservada, ya que el montón debe ser un espacio de direcciones continuo. Si no se reservara previamente, podría suceder que el montón no se pudiera expandir a este valor máximo, porque alguien más reservó una región de espacio de direcciones en el lugar donde el montón debe expandirse.
Los tamaños predeterminados para el montón inicial y el montón máximo se definen como un porcentaje de la memoria física de la máquina, de la cual un servidor de producción en la actualidad tiende a tener mucho .
Puede elegir ambos a través de las opciones de línea de comando -Xms y -Xmx .
No es su programa el que consume esa memoria, es la VM Java que reserva esa memoria, independientemente de qué programa esté cargado.
Resulta que en una arquitectura de computadora moderna que usa direccionamiento de memoria virtual (donde el "espacio de memoria" que ve una aplicación no se relaciona realmente con la memoria que está físicamente asignada), realmente no importa cuánto de este "espacio de memoria virtual" "se da a una aplicación al inicio. No significa que el sistema haya asignado esta cantidad de memoria.
Si una aplicación ve un espacio de direcciones virtual de 10 GB de ancho, todo lo que señala a la aplicación es que puede usar direcciones de memoria de hasta 10 GB si lo desea. Sin embargo, la memoria no está realmente asignada en la RAM física hasta que realmente se haya escrito, y esto se hace página por página, donde una página es una sección de memoria de 4kB. El espacio de direcciones virtuales es solo eso, completamente virtual hasta que realmente se usa.
Digamos que una aplicación recibe 10 GB de espacio de direcciones y comienza a usar parte de ella. Como una página "nueva" - previamente intacta - de esta memoria virtual se escribe por primera vez, el sistema, en un nivel bajo, "asignará" esta página virtual a una sección de la memoria física, y luego la escribirá. Pero esa aplicación en sí no tiene que preocuparse por esos detalles, solo actúa como si tuviera acceso completo a un área virtual de memoria.
En el caso de las aplicaciones Java, no es la aplicación en sí, sino que Java tiene asignado ese espacio de direcciones, y Java simplemente solicita un gran espacio de direcciones de manera predeterminada: el monto que solicita se calcula en relación con el tamaño de la memoria física, pero no porque cualquier necesidad de ser conservador, pero solo por cuestiones prácticas: una aplicación probablemente no va a querer un tamaño de pila suficiente como para poner por completo de rodillas a un servidor, por lo que está funcionando bajo la suposición de que no lo hará. Como dije antes, esto no significa que esto esté "asignado" o que el sistema haya tenido que gastar muchos recursos para hacerlo.
Tu programa NO usa tanta memoria. JVM / OS está reservando esa memoria, es decir, el límite HASTA QUE su programa puede usar. Además, como una de las respuestas claramente menciona. 32 bit y 64 bit no tienen nada que ver con esto. 32 bits significa que puede acceder a hasta 2 ^ 32 ubicaciones de memoria física. y 64 bits significa hasta 2 ^ 64.