¿Por qué la JVM requiere calentamiento?


Entiendo que en la máquina virtual Java (JVM), el calentamiento es potencialmente necesario cuando Java carga clases usando un proceso de carga lenta y, como tal, desea asegurarse de que los objetos se inicialicen antes de iniciar las transacciones principales. Soy un desarrollador de C++ y no he tenido que lidiar con requisitos similares.

Sin embargo, las partes que no puedo entender son las siguientes:

  1. ¿Qué partes del código debes calentar?
  2. Incluso si caliento algunas partes del código, ¿cuánto tiempo permanece caliente (suponiendo que este término solo significa cuánto tiempo permanecen los objetos de clase en la memoria)?
  3. ¿Cómo ayuda si tengo objetos que necesitan ser creados cada vez que recibo un evento?

Considere como ejemplo una aplicación que se espera que reciba mensajes a través de un socket y las transacciones podrían ser New Order, Modify Order y Cancel Order o transaction confirmed.

Tenga en cuenta que la aplicación se trata de Comercio de Alta Frecuencia (HFT) así que el rendimiento es de extrema importancia.

Author: Peter Lawrey, 2016-03-24

7 answers

¿Qué partes del código debes calentar?

Por lo general, no tienes que hacer nada. Sin embargo, para una aplicación de baja latencia, debe calentar la ruta crítica en su sistema. Deberías tener pruebas unitarias, así que sugiero que las ejecutes en el arranque para calentar el código.

Incluso una vez que su código se calienta, usted tiene que asegurarse de que sus cachés de CPU se mantienen calientes también. Puede ver una desaceleración significativa en el rendimiento después de una operación de bloqueo, por ejemplo, network IO, para arriba a 50 microsegundos. Por lo general, esto no es un problema, pero si usted está tratando de permanecer por debajo de decir 50 micro-segundos la mayor parte del tiempo, esto será un problema la mayor parte del tiempo.

Nota: El calentamiento puede permitir que el Análisis de Escape se active y coloque algunos objetos en la pila. Esto significa que estos objetos no necesitan ser optimizados. Es mejor perfilar la memoria de su aplicación antes de optimizar su código.

Incluso si caliento algunas partes del código, cuánto tiempo permanece caliente (suponiendo que este término solo significa cuánto tiempo permanecen los objetos de clase en la memoria)?

No hay límite de tiempo. Depende de si el JIt detecta si la suposición que hizo al optimizar el código resultó ser incorrecta.

¿Cómo ayuda si tengo objetos que necesitan ser creados cada vez que recibo un evento?

Si desea baja latencia o alto rendimiento, debe crear el menor número posible de objetos. Mi objetivo es producir menos de 300 KB / seg. Con esta tasa de asignación, puede tener un espacio Eden lo suficientemente grande como para recolectar una vez al día.

Considere como ejemplo una aplicación que se espera que reciba mensajes a través de un socket y las transacciones podrían ser New Order, Modify Order y Cancel Order o transaction confirmed.

Le sugiero que reutilice los objetos tanto como sea posible, aunque si está bajo su presupuesto de asignación, puede que no valga la pena preocuparse.

Tenga en cuenta que la la aplicación se trata de Comercio de Alta Frecuencia (HFT), por lo que el rendimiento es de extrema importancia.

Usted podría estar interesado en nuestro software de código abierto que se utiliza para los sistemas HFT en diferentes Bancos de Inversión y Fondos de Cobertura.

Http://chronicle.software /

Mi aplicación de producción se utiliza para el comercio de alta frecuencia y cada bit de latencia puede ser un problema. Es un poco claro que en el inicio si no calienta su aplicación, conducirá a alta latencia de pocos milis.

En particular, podría estar interesado en https://github.com/OpenHFT/Java-Thread-Affinity ya que esta biblioteca puede ayudar a reducir la fluctuación de programación en sus subprocesos críticos.

Y también se dice que las secciones críticas del código que requieren calentamiento deben ejecutarse (con mensajes falsos) al menos 12K veces para que funcione de manera optimizada. Por qué y cómo funciona?

El código se compila usando background hilo(s). Esto significa que aunque un método podría ser elegible para compilar a código nativo, no significa que lo haya hecho esp al inicio cuando el compilador ya está bastante ocupado. 12K no es irrazonable, pero podría ser mayor.

 22
Author: Peter Lawrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 22:02:50

Warming se refiere a tener una pieza de código ejecutada las veces suficientes para que la JVM deje de interpretar y compile a nativo (al menos por primera vez). Generalmente eso es algo que no quieres hacer. La razón es que la JVM recopila estadísticas sobre el código en cuestión que utiliza durante la generación de código (similar a las optimizaciones guiadas por perfiles). Entonces, si un fragmento de código en cuestión está "calentado" con datos falsos que tienen propiedades diferentes a los datos reales, bien podría estar perjudicando rendimiento.

EDIT: Dado que la JVM no puede realizar análisis estáticos de todo el programa (no puede saber qué código va a cargar la aplicación), puede hacer algunas conjeturas sobre los tipos a partir de las estadísticas que ha recopilado. Como ejemplo, cuando se llama a una función virtual (en lenguaje C++) en una ubicación de llamada exacta y se determina que todos los tipos tienen la misma implementación, entonces la llamada se promueve a llamada directa (o incluso en línea). Si más tarde esa suposición si se demuestra que incorrecto, entonces el código antiguo debe estar" sin compilar " para comportarse correctamente. AFAIK HotSpot clasifica los sitios de llamada como monomórficos (implementación única), bimórficos (exactamente dos..transformado en if (imp1-type) {imp1} else {imp2}) y polimórfico completo..despacho virtual.

Y hay otro caso en el que se produce la recompilación..cuando tienes niveles-compilación. El primer nivel pasará menos tiempo tratando de producir buen código y si el método es "lo suficientemente caliente", entonces el tiempo de compilación más costoso el generador de código entra en acción.

 18
Author: MB Reynolds,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 13:08:23

El calentamiento rara vez se requiere . Es relevante al hacer, por ejemplo, pruebas de rendimiento, para asegurarse de que el tiempo de calentamiento JIT no sesgue los resultados.

En el código de producción normal rara vez se ve el código que está destinado para el calentamiento. El JIT se calentará durante el procesamiento normal, por lo que hay muy poca ventaja para introducir código adicional solo para eso. En el peor de los casos, podría estar introduciendo errores, pasando tiempo de desarrollo adicional e incluso dañando rendimiento.

A menos que sepas con certeza que necesitas algún tipo de calentamiento, no te preocupes. La aplicación de ejemplo que describiste ciertamente no lo necesita.

 9
Author: Kayaman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 10:57:38

¿Qué partes del código debe calentar?

No hay respuesta a esta pregunta en general. Depende completamente de su aplicación.

Incluso si caliento algunas partes del código, cuánto tiempo permanece caliente (suponiendo que este término solo significa cuánto tiempo permanecen los objetos de clase in-memory)?

Los objetos permanecen en la memoria durante el tiempo que su programa tenga una referencia a ellos, sin ningún uso especial de referencia débil o algo similar. Aprendizaje acerca de cuando su programa "tiene una referencia" a algo puede ser un poco más oscuro de lo que podría pensar a primera vista, pero es la base para la gestión de memoria en Java y vale la pena el esfuerzo.

¿Cómo ayuda si tengo objetos que necesitan ser creados cada vez Recibo un evento.

Esto depende completamente de la aplicación. No hay respuesta en general.

Te animo a estudiar y trabajar con Java para entender cosas como classloading, gestión de la memoria y supervisión del rendimiento. Se necesita cierta cantidad de tiempo para instanciar un objeto, en general se necesita más tiempo para cargar una clase (que, por supuesto, generalmente se hace con mucha menos frecuencia). Normalmente, una vez que se carga una clase, permanece en la memoria durante toda la vida del programa this este es el tipo de cosas que debes entender, no solo obtener una respuesta.

También hay técnicas para aprender si no las conoces ya. Algunos programas utilizan "pools" de objetos, instanciados antes de que sean realmente necesarios, luego entregados para hacer el procesamiento una vez que surja la necesidad. Esto permite una parte crítica del programa para evitar el tiempo dedicado a crear instancias durante el período crítico de tiempo. Las piscinas mantienen una colección de objetos (10? 100? 1000? 10000?), e instanciar más si es necesario, etc. Pero administrar los pools es un esfuerzo de programación significativo, y, por supuesto, ocupas memoria con los objetos en los pools.

Sería enteramente es posible utilizar suficiente memoria para activar la recolección de basura mucho más a menudo, y RALENTIZAR EL SISTEMA QUE PRETENDÍA ACELERAR. Es por eso que necesitas entender cómo funciona, no solo "obtener una respuesta".

Otra consideración by con mucho, la mayor parte del esfuerzo puesto en hacer programas más rápidos se desperdicia, ya que no es necesario. Sin una amplia experiencia con la aplicación que se está considerando, y / o la medición del sistema, simplemente no sabe dónde (o si) la optimización incluso será notable. El diseño del sistema / programa para evitar casos patológicos de lentitud ES útil, y no toma casi el tiempo y el esfuerzo de 'optimización'. La mayoría de las veces es todo lo que cualquiera de nosotros necesita.

Edit edit add añade la compilación just-in-time a la lista de cosas para estudiar y entender.

 2
Author: arcy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 11:06:41

¿Por qué JVM requiere calentamiento?

Las máquinas virtuales modernas (J)recopilan estadísticas en tiempo de ejecución sobre qué código se usa con más frecuencia y cómo se usa. Un ejemplo (de cientos si no miles) es la optimización de llamadas a funciones virtuales (en la jerga de C++) que tienen solo en la implementación. Por definición, esas estadísticas solo pueden recopilarse en tiempo de ejecución.

La carga de clases en sí misma también es parte del calentamiento, pero obviamente sucede automáticamente antes de la ejecución del código dentro de esas clases, así que no hay mucho de qué preocuparse

¿Qué partes del código debe calentar?

La parte que es crucial para el rendimiento de su aplicación. La parte importante es "calentarlo" de la misma manera que se usa durante el uso normal, de lo contrario se realizarán optimizaciones incorrectas (y se desharán más adelante).

Incluso si caliento algunas partes del código, cuánto tiempo permanece caliente (suponiendo que este término solo significa cuánto tiempo su los objetos de clase permanecen en la memoria)?

Esto es realmente difícil de decir básicamente el compilador JIT monitorea constantemente la ejecución y el rendimiento. Si se alcanza alguna trilla, tratará de optimizar las cosas. A continuación, continuará supervisando el rendimiento para verificar que la optimización realmente ayuda. Si no, podría no optimizar el código. También pueden ocurrir cosas que invaliden optimizaciones, como la carga de nuevas clases. Consideraría esas cosas no predecibles, al menos no basadas en un respuesta de stackoverflow, pero hay herramientas que te dicen lo que está haciendo el JIT: https://github.com/AdoptOpenJDK/jitwatch

¿Cómo ayuda si tengo objetos que necesitan ser creados cada vez que recibo un evento?

Un ejemplo simple podría ser: se crean objetos dentro de un método, ya que una referencia sale del ámbito del método, esos objetos se almacenarán en el montón, y eventualmente serán recogidos por el recolector de basura. Si el código que utiliza esos objetos es muy utilizado, podría terminar siendo inlineado en un solo método grande, posiblemente reordenado más allá del reconocimiento, hasta que estos objetos solo viven dentro de este método. En ese punto se pueden poner en la pila y se eliminan cuando el método sale. Esto puede ahorrar grandes cantidades de recolección de basura y solo sucederá después de un poco de calentamiento.

Con todo lo dicho: Soy escéptico sobre la noción de que uno necesita hacer algo especial para calentar. Simplemente inicie su aplicación, y úsela y el JIT el compilador lo hará bien. Si experimenta problemas, aprenda qué hace el JIT con su aplicación y cómo ajustar ese comportamiento o cómo escribir su aplicación para que se beneficie al máximo.

El único caso en el que realmente sé sobre la necesidad de calentamiento son los puntos de referencia. Porque si se descuida allí obtendrá resultados falsos casi garantizados.

 2
Author: Jens Schauder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 11:09:25

Se trata de JIT compilador, que se utiliza en el JVM para optimizar el bytecode en el tiempo de ejecución (porque javac no puede usar técnicas de optimización avanzadas o agresivas debido a la naturaleza independiente de la plataforma del bytecode)

  1. Puedes calentar el código que procesará tus mensajes. En realidad, en la mayoría de los casos no es necesario hacerlo mediante ciclos de calentamiento especiales: simplemente deje que la aplicación inicie y procese algunos de los primeros mensajes - JVM intentará hacer todo lo posible para analizar el código ejecución y hacer optimizaciones :) Calentamiento manual con muestras falsas puede dar resultados aún peores

  2. El código se optimizará después de cierto tiempo y se optimizará hasta que algún evento en el flujo del programa degradará el estado del código (después de esto JIT el compilador intentará optimizar el código nuevamente - este proceso nunca termina)

  3. Los objetos de vida corta también son sujetos que deben optimizarse, pero generalmente deberían ayudar a que el procesamiento de mensajes sea más eficiente

 2
Author: Cootri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 11:21:18

Siempre lo imaginé de la siguiente manera:

Usted como (un desarrollador de C++) podría imaginar un automatizado enfoque iterativo por el jvm compilar/hotloading/reemplazar varios bits y piezas con (el análogo imaginario de) gcc -O0,-O1,-O2,-O3 variantes (y a veces revertirlas si lo considera necesario)

Estoy seguro de que esto no es estrictamente lo que sucede, pero podría ser una analogía útil para un desarrollador de C++.

En una jvm estándar las veces que toma un fragmento para ser considerado para jit se establece por -XX:CompileThreshold que es 1500 por defecto. (Fuentes y versiones jvm varían-pero creo que eso es para jvm8)

Además, un libro que tengo a mano establece en el Capítulo JIT de Host Performace (p59) que las siguientes optimizaciones se realizan durante JIT:

  • Inlining
  • Eliminación de bloqueo
  • Eliminación de llamadas virtuales
  • Eliminación de escritura de memoria no volátil
  • código Nativo generación

EDITAR:

Respecto a los comentarios

Creo que 1500 puede ser suficiente para insinuar a JIT que debería compilar el código en nativo y dejar de interpretar. ¿estás de acuerdo?

No se si es solo una pista, pero ya que openjdk es de código abierto veamos los varios límites y números en globales.hpp # l3559@ver-a801bc33b08c (para jdk8u)

(No soy un desarrollador de jvm este podría ser el lugar completamente equivocado para mira)

Compilar un código en nativo no significa necesariamente que sea también optimizar.

A mi entender - cierto; especialmente si te refieres a -Xcomp (force compile) - este blog incluso afirma que impide que la jvm haga cualquier perfil - por lo tanto, la optimización - si no se ejecuta -Xmixed (el valor predeterminado).

Así que un temporizador se activa para muestrear el código nativo al que se accede con frecuencia y optimiza el mismo. ¿Sabes cómo podemos controlar este temporizador intervalo?

Realmente no conozco los detalles, pero el gobals.hpp enlazado de hecho define algunos intervalos de frecuencia.

 1
Author: birdspider,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-25 14:31:30