utiliza sirve qué que para máquina interprete implicaciones desarrollo compilador como bytecodes java performance memory jvm

java - sirve - Monitorear el uso de la memoria no en pilas de una JVM



que es un interprete en java (3)

Su montón está usando 6.5 GB de memoria virtual (esto puede incluir el gen de permanente)

Tienes un montón de hilos usando pilas de 64 MB. No está claro por qué algunos son y otros están utilizando el predeterminado de 1 MB.

El total es 9.3 millones de KB de memoria virtual. Solo me preocuparía el tamaño del residente.

Intenta usar la top para encontrar el tamaño residente del proceso.

Puede encontrar este programa útil

BufferedReader br = new BufferedReader(new FileReader("C:/dev/gistfile1.txt")); long total = 0; for(String line; (line = br.readLine())!= null;) { String[] parts = line.split("[- ]"); long start = new BigInteger(parts[0], 16).longValue(); long end = new BigInteger(parts[1], 16).longValue(); long size = end - start + 1; if (size > 1000000) System.out.printf("%,d : %s%n", size, line); total += size; } System.out.println("total: " + total/1024);

A menos que tenga una biblioteca JNI que use la memoria, supongo que tiene muchos hilos que tienen su propio espacio de pila. Verificaría la cantidad de hilos que tienes. Puede reducir el espacio máximo de pila por subproceso, pero una mejor opción podría ser reducir el número de subprocesos que tiene.

La memoria de almacenamiento dinámico externo no está, por definición, administrada, por lo que no se puede "sintonizar" fácilmente como tal. Incluso ajustar el montón no es simple.

El tamaño de pila predeterminado en las JVM de 64 bits es 1024 K, por lo que 700 subprocesos usarán 700 MB de memoria virtual.

No debe confundir los tamaños de la memoria virtual con los tamaños de memoria residentes. La memoria virtual en una aplicación de 64 bits es casi gratuita y solo debe preocuparse por el tamaño del residente.

De la forma en que lo veo, tienes 9.3 GB en total.

  • 6.0 GB de almacenamiento.
  • 128 MB perm gen
  • 700 MB de pilas.
  • <250 bibliotecas compartidas
  • 2.2 GB de memoria desconocida (sospecho que memoria virtual no residente)

La última vez que alguien tuvo este problema, tuvieron muchos más hilos de los que deberían. Verificaría el número máximo de hilos que tenía, ya que es el pico el que determina el tamaño virtual. por ejemplo, ¿estaba más cerca de 3000?

Hmmm cada uno de estos pares es un hilo.

7f0cffddf000-7f0cffedd000 rw-p 00000000 00:00 0 7f0cffedd000-7f0cffee0000 ---p 00000000 00:00 0

y estos sugieren que tienes un poco menos de 700 hilos ahora ...

Por lo general, nos ocupamos de los problemas OutOfMemoryError debido al problema de configuración de tamaño de montón o permgen.

Pero toda la memoria JVM no es permgen o heap. Por lo que yo entiendo, también puede estar relacionado con Threads / Stacks, código JVM nativo ...

Pero al usar pmap puedo ver que el proceso se asigna con 9.3G, que es el uso de la memoria fuera de montón 3.3G.

Me pregunto cuáles son las posibilidades de monitorear y ajustar este consumo extra de memoria fuera de mi memoria.

No uso el acceso directo a la memoria externa (MaxDirectMemorySize es 64m por defecto)

Context: Load testing Application: Solr/Lucene server OS: Ubuntu Thread count: 700 Virtualization: vSphere (run by us, no external hosting)

JVM

java version "1.7.0_09" Java(TM) SE Runtime Environment (build 1.7.0_09-b05) Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)

Tunning

-Xms=6g -Xms=6g -XX:MaxPermSize=128m -XX:-UseGCOverheadLimit -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:+OptimizeStringConcat -XX:+UseCompressedStrings -XX:+UseStringCache

Mapas de memoria:

https://gist.github.com/slorber/5629214

vmstat

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa 1 0 1743 381 4 1150 1 1 60 92 2 0 1 0 99 0

gratis

total used free shared buffers cached Mem: 7986 7605 381 0 4 1150 -/+ buffers/cache: 6449 1536 Swap: 4091 1743 2348

Parte superior

top - 11:15:49 up 42 days, 1:34, 2 users, load average: 1.44, 2.11, 2.46 Tasks: 104 total, 1 running, 103 sleeping, 0 stopped, 0 zombie Cpu(s): 0.5%us, 0.2%sy, 0.0%ni, 98.9%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 8178412k total, 7773356k used, 405056k free, 4200k buffers Swap: 4190204k total, 1796368k used, 2393836k free, 1179380k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 17833 jmxtrans 20 0 2458m 145m 2488 S 1 1.8 206:56.06 java 1237 logstash 20 0 2503m 142m 2468 S 1 1.8 354:23.19 java 11348 tomcat 20 0 9184m 5.6g 2808 S 1 71.3 642:25.41 java 1 root 20 0 24324 1188 656 S 0 0.0 0:01.52 init 2 root 20 0 0 0 0 S 0 0.0 0:00.26 kthreadd ...

df -> tmpfs

Filesystem 1K-blocks Used Available Use% Mounted on tmpfs 1635684 272 1635412 1% /run

El principal problema que tenemos:

  • El servidor tiene 8G de memoria física
  • El montón de Solr lleva solo 6G
  • Hay 1.5G de intercambio
  • Swappiness = 0
  • El consumo de pila parece estar apropiadamente sincronizado
  • Corriendo en el servidor: solo Solr y algunas cosas de monitoreo
  • Tenemos un tiempo de respuesta promedio correcto
  • A veces tenemos pausas anormalmente largas, de hasta 20 segundos

Supongo que las pausas podrían ser un GC completo en un montón intercambiado, ¿verdad?

¿Por qué hay tanto intercambio?

Ni siquiera sé realmente si esta es la JVM que hace que el servidor se intercambie o si es algo oculto que no puedo ver. Tal vez el caché de la página del sistema operativo? Pero no estoy seguro de por qué el sistema operativo crearía entradas de caché de página si eso crea intercambio.

Estoy considerando probar el truco de mlockall utilizado en algunos populares de almacenamiento basado en Java / NoSQL como ElasticSearch, Voldemort o Cassandra: comprobar Hacer que JVM / Solr no intercambie, utilizando mlockall

Editar:

Aquí puede ver el montón máximo, el montón usado (azul), un intercambio usado (rojo). Parece algo relacionado.

Puedo ver con Graphite que hay muchos ParNew GC que ocurren regularmente. Y hay algunos CMS GC que corresponden al montón de disminuciones significativas de la imagen.

Las pausas no parecen correlacionarse con las disminuciones del montón, pero se distribuyen regularmente entre las 10:00 y las 11:30, por lo que podría estar relacionado con el GC de ParNew, supongo.

Durante la prueba de carga, puedo ver cierta actividad del disco y también alguna actividad de intercambio IO que es realmente tranquila cuando termina la prueba.


Una forma bastante conveniente de supervisar (y cambiar parcialmente) los parámetros de tiempo de ejecución de una instancia de JVM es VisualVM:

PD
(eliminado)

PPS. Recordé la otra herramienta que utilicé hace un tiempo: Visual GC . Le muestra visualmente en detalle lo que sucede dentro de la administración de la memoria JVM, aquí algunas screenshots . Muy potente, e incluso se puede integrar con un complemento en VisualVM (consulte la sección de complementos en la página de inicio de VisualVM).

PPPS
We sometimes have anormaly long pauses, up to 20 seconds. [...] I guess the pauses could be a full GC on a swapped heap right?
Sí, eso podría ser. Que las pausas largas pueden ser causadas por GC completo incluso en montones no intercambiados. Con VisualVM puede controlar si ocurre un GC completo en el momento en que ocurre la pausa de ~ 20 segundos. Sugiero ejecutar VisualVM en otro host y conectarlo al proceso de JVM en su servidor virtual a través de JMX explícito , para no falsificar las mediciones con carga adicional. Puede dejar que la configuración se ejecute durante días / semanas y, por lo tanto, recopilar información definitiva sobre el fenómeno.

Afaics con información actual, por el momento solo existen estas posibilidades:

  • las pausas observadas ocurren simultáneamente con GC completo: la JVM no está ajustada correctamente. Puede aliviar esto a través de los parámetros de JVM, y tal vez elegir otro algoritmo / motor de GC (¿ha probado CMS y G1 GC? Más información acerca de cómo sucede esto, por ejemplo, here )
  • las pausas observadas no coinciden con un GC completo en la JVM: el host virtual físico podría ser la causa. Verifique sus acuerdos de nivel de servicio (cantidad de RAM virtual garantizada en la memoria RAM física) y póngase en contacto con su proveedor de servicios para supervisar el servidor virtual.

Debería haber mencionado que VisualVM se envía con Java. Y JConsole, también incluido con Java, que es más liviano y más compacto que VisualVM (pero no tiene complementos, sin perfiles, etc.), pero ofrece una visión general similar.

Si la configuración de la conexión JMX para VisualVM / JConsole / VisualGC es demasiado complicada por el momento, puede recurrir a los siguientes parámetros java: -XX:+PrintGC -XX:+PrintGCTimeStamps -Xloggc:/my/log/path/gclogfile.log . Estos parámetros harán que la JVM escriba en el archivo de registro especificado una entrada para cada ejecución de GC. Esta opción también es adecuada para el análisis a largo plazo, y es probablemente la que menos gastos generales tiene en su JVM.

Después de pensar nuevamente (y de nuevo) sobre su pregunta: si se pregunta de dónde provienen los 3+ GB adicionales, aquí tiene una pregunta relacionada . Yo personalmente uso el factor x1.5 como regla general.


Usando jps y jstat puede simplemente rastrear los detalles de la memoria de su programa java.

Encuentre el comando pid usando jps y use ese pid para obtener los detalles de la memoria de su proceso java deseado usando jstat $pid . Si es necesario, ejecútelos en un bucle y podrá monitorear de cerca los detalles de la memoria que desee.

Puedes encontrar una implementación de bash de esta idea en github