Cantidad máxima de memoria por proceso de Java en Windows?

¿Cuál es el tamaño máximo de almacenamiento dynamic que puede asignar en Windows de 32 bits para un proceso Java utilizando -Xmx ?

Lo estoy preguntando porque quiero usar los datos de ETOPO1 en OpenMap y el archivo flotante binario en bruto tiene aproximadamente 910 MB.

No hay nada mejor que un experimento empírico para responder a tu pregunta. Escribí un progtwig Java y lo ejecuté mientras especificaba el indicador XMX (también usé XMS = XMX para forzar a la JVM a preasignar toda la memoria). Para proteger aún más contra las optimizaciones de JVM, he asignado activamente un número X de objetos de 10MB. Ejecuto una serie de pruebas en varias JVM que aumentan el valor de XMX junto con el aumento del número de MB asignados, en sistemas operativos de 32 bits diferentes que utilizan ambas JVM de Sun e IBM. A continuación, presentamos un resumen de los resultados:

Sistema operativo: Windows XP SP2, JVM: Dom 1.6.0_02, Tamaño máximo del almacenamiento dynamic: 1470 MB
Sistema operativo: Windows XP SP2, JVM: IBM 1.5, Tamaño máximo del almacenamiento dynamic: 1810 MB
Sistema operativo: Windows Server 2003 SE, JVM: IBM 1.5, Tamaño máximo del almacenamiento dynamic: 1850 MB
Sistema operativo: Linux 2.6, JVM: IBM 1.5, tamaño máximo de almacenamiento dynamic: 2750 MB

Aquí están los bashs de ejecución detallados junto con el código fuente auxiliar de la clase de asignación:

WinXP SP2, SUN JVM:

 C:> java -version
 versión de java "1.6.0_02"
 Java (TM) SE Runtime Environment (comstackción 1.6.0_02-b06)
 Java HotSpot (TM) Client VM (comstackción 1.6.0_02-b06, modo mixto) 

java -Xms1470m -Xmx1470m Class1 142

a punto de crear el objeto 141
objeto 141 creado

C:> java -Xms1480m -Xmx1480m Class1 145
Se produjo un error durante la inicialización de la VM
No se pudo reservar suficiente espacio para el montón de objetos
No se pudo crear la máquina virtual de Java.
WinXP SP2, IBM JVM

 
 C:> c: \ ibm \ jdk \ bin \ java.exe -version
 versión java "1.5.0"
 Java (TM) 2 Runtime Environment, Standard Edition (comstackción pwi32devifx-20070323 (si
 ix 117674: SR4 + 116644 + 114941 + 116110 + 114881))
 IBM J9 VM (versión 2.3, J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32 j9vmwi3223ifx-2007
 0323 (JIT habilitado)
 J9VM - 20070322_12058_lHdSMR
 JIT - 20070109_1805ifx3_r8
 GC - WASIFIX_2007)
 JCL - 20070131 

c: \ ibm \ jdk \ bin \ java.exe -Xms1810m -Xmx1810m Class1 178

a punto de crear el objeto 177
objeto 177 creado

C:> c: \ ibm \ jdk \ bin \ java.exe -Xms1820m -Xmx1820m Class1 179
JVMJ9VM015W Error de inicialización para la biblioteca j9gc23 (2): Error al instanciarlo
ap. 1820M solicitado
No se pudo crear la máquina virtual de Java.
Win2003 SE, IBM JVM

 C:> "C: \ IBM \ java" -Xms1850m -Xmx1850m Class1
 durmiendo por 5 segundos.
 Hecho. 

C:> “C: \ IBM \ java” -Xms1880m -Xmx1880m
Clase 1
JVMJ9VM015W Error de inicialización para la biblioteca j9gc23 (2): Error al instanciarlo
ap. 1880M solicitado
No se pudo crear la máquina virtual de Java. Linux 2.6, IBM JVM

 [root @ myMachine ~] # / opt / ibm / java2-i386-50 / bin / java -version
 versión java "1.5.0"
 Java (TM) 2 Runtime Environment, Standard Edition (comstackción pxi32dev-20060511 (SR2))
 IBM J9 VM (comstackción 2.3, J2RE 1.5.0 IBM J9 2.3 Linux x86-32 j9vmxi3223-20060504 (JIT habilitado)
 J9VM - 20060501_06428_lHdSMR
 JIT - 20060428_1800_r8
 GC - 20060501_AA)
 JCL - 20060511a 

/ opt / ibm / java2-i386-50 / bin / java -Xms2750m -Xmx2750m Class1 270

[root @ myMachine ~] # / opt / ibm / java2-i386-50 / bin / java -Xms2800m -Xmx2800m Class1 270
JVMJ9VM015W Error de inicialización para la biblioteca j9gc23 (2): Error al crear instancias de heap. 2800M solicitado
No se pudo crear la máquina virtual de Java.

Aquí está el código:

 import java.util.StringTokenizer; public class Class1 { public Class1() {} private class BigObject { byte _myArr[]; public BigObject() { _myArr = new byte[10000000]; } } public static void main(String[] args) { (new Class1()).perform(Integer.parseInt(args[0])); } public void perform(int numOfObjects) { System.out.println("creating 10 MB arrays."); BigObject arr[] = new BigObject[numOfObjects]; for (int i=0;i  

Para un archivo grande, sugiero que use un archivo mapeado de memoria. Esto no usa el espacio de montón (o muy poco) para que el tamaño máximo de almacenamiento dynamic no sea un problema en este caso.

Recientemente hemos migrado de Windows a Linux (debido a problemas de tamaño de VM).

He oído hablar de muchos números arrojados en el pasado para Windows VM size (1200, 1400, 1600, 1800). En nuestros Servidores de Windows (2003), en nuestro entorno, con nuestras aplicaciones , … Nunca he utilizado con éxito más de 1280 MB. Más allá de eso, nuestra aplicación comenzó a exhibir problemas de GC y OOM.

Cada vez que obtuve una nueva versión de VM intenté cambiar el número y nunca varió.

Ahora tiene un archivo de 900 MB, ¿qué sucede si el archivo aumenta a 1300 MB? ¿Qué harás?

Tienes un número de opciones

  1. Puerto a Linux / Solaris. Esto solo necesita hardware / software y lo que a menudo es un simple ejercicio de portabilidad.
  2. Usa Windows de 64 bits. Sin embargo, esto puede no estar libre de problemas de GC: he oído hablar de diferentes historias con vms de 64 bits.
  3. Rediseñe la aplicación para procesar el archivo de forma diferente. ¿Puede dividir el archivo lógicamente de alguna manera, puede leer el archivo en fragmentos y procesarlo de manera diferente, etc.?

Otras personas que usan OpenMap deben haber encontrado este problema. ¿Puedes aprovechar su conocimiento y no reinventar ninguna rueda?

Como se señaló en la pregunta mencionada en el comentario, hay un límite práctico, alrededor de 1200 MB.

Sin embargo, la situación que describes tiene más profundidad que el tamaño de la memoria pura.

Cuando lee datos binarios de 910 MB y crea objetos de red fuera de él (en lugar de simplemente mantener los datos como una matriz de bytes), termina consumiendo mucha más memoria que 910 MB. Una estimación razonable sería que la representación en memoria consumirá el doble de memoria, porque (1) cada objeto contiene un puntero adicional (a la clase del objeto); y (2) hay muchos datos de contabilidad. Por ejemplo, si usa un HashMap para administrar sus objetos, además de cada objeto, también asigna un objeto Map.Entry que puede consumir fácilmente 16 o 20 bytes (depende de la implementación).

Por otro lado, todavía hay esperanza: ¿realmente necesita mantener todos los 910 MB en la memoria? ¿No puedes simplemente construir algo que lea los datos de una manera perezosa? Combinado con WeakReferences, creo que puedes lograrlo.

En Windows de 32 bits, de forma predeterminada, cada aplicación puede usar hasta 2 GB de espacio de direcciones virtual. Supongo que esto hace que -Xmx2048M . Sin embargo, si tiene más RAM instalada, puede boost el espacio de direcciones virtuales de hasta 3 GB mediante el uso de parámetros de tiempo de inicio.

En boot.ini, puede crear nuevas opciones de arranque como esta:

 [boot loader]
timeout=5
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional - magyar" /noexecute=optin /fastdetect /usepmtimer
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional - magyar 3GB" /noexecute=optin /fastdetect /usepmtimer /3GB /USERVA=2800

Aquí ajustando el parámetro / USERVA = 2800, puede sintonizar su máquina. Pero tenga en cuenta que a algunas configuraciones no les gustan los valores altos en este parámetro: esperan choques.