java - test - ¿Por qué la JVM es lenta para comenzar?
run cucumber feature from command line (8)
¿Qué es exactamente lo que hace que la JVM (en particular, la implementación de Sun) tarden en ejecutarse en comparación con otros tiempos de ejecución como CPython? Mi impresión es que principalmente tiene que ver con un montón de bibliotecas cargadas, ya sea que las necesiten o no, pero eso parece algo que no debería tardar 10 años en solucionar.
Ahora que lo pienso, ¿cómo se compara el tiempo de inicio de JVM con el CLR en Windows? ¿Qué tal el CLR de Mono?
ACTUALIZACIÓN: estoy particularmente preocupado con el caso de uso de pequeñas utilidades encadenadas como es común en Unix. ¿Es Java ahora adecuado para este estilo? Cualquiera que sea el inicio de arranque en el que incurra Java, ¿se suma para cada proceso de Java, o la sobrecarga solo se manifiesta realmente para el primer proceso?
Además de las cosas ya mencionadas (cargar clases, especialmente desde JAR comprimidos); ejecutándose en modo interpretado antes de que HotSpot compile bytecode de uso común; Una sobrecarga de compilación de HotSpot, también hay bastante inicialización hecha por las propias clases de JDK. Se realizan muchas optimizaciones a favor de sistemas de más tiempo en los que la velocidad de inicio es menos preocupante.
Y en cuanto a la canalización de estilo de Unix: ciertamente NO querrás iniciar y reiniciar JVM varias veces. Eso no va a ser eficiente. Más bien, el encadenamiento de herramientas debería ocurrir dentro de JVM. Esto no se puede mezclar fácilmente con herramientas que no sean Java Unix, excepto al iniciar dichas herramientas desde dentro de JVM.
Ejecutar una aplicación Java trivial con el cliente 1.6 (Java 6) JVM parece instantáneo en mi máquina. Sun ha intentado sintonizar la JVM del cliente para un inicio más rápido (y la JVM del cliente es la predeterminada), por lo que si no necesita muchos archivos jar adicionales, el inicio debería ser rápido.
Esto es lo que Wikipedia tiene que decir sobre el tema (con algunas referencias).
Parece que la mayor parte del tiempo se toma simplemente cargando datos (clases) desde el disco (es decir, el tiempo de inicio está vinculado a E / S).
Hay un número de razones:
- muchos
jar
s para cargar - verificación (asegurándose de que el código no haga cosas malas)
- JIT (compilación justo a tiempo)
No estoy seguro del CLR, pero creo que a menudo es más rápido porque almacena en caché una versión nativa de ensamblajes para la próxima vez (por lo que no necesita JIT). CPython se inicia más rápido porque es un intérprete, y IIRC, no hace JIT.
Realmente depende de lo que estés haciendo durante la puesta en marcha. Si ejecuta la aplicación Hello World, demorará 0.15 segundos en mi máquina.
Sin embargo, Java es más adecuado para ejecutarse como cliente o servidor / servicio, lo que significa que el tiempo de inicio no es tan importante como el tiempo de conexión (aproximadamente 0.025 ms) o el tiempo de respuesta de tiempo de ida y vuelta (<< 0.001 ms).
Si está utilizando SunS HotSpot para x86_64 (compilación de 64 bits), tenga en cuenta que la implementación actual solo funciona en modo servidor, es decir, precompila cada clase que carga con optimización total, mientras que la versión de 32 bits también admite el modo cliente, que generalmente pospone la optimización y optimiza la mayoría de las piezas con uso intensivo de CPU, pero tiene tiempos de arranque más rápidos.
Ver por ejemplo:
- http://en.wikipedia.org/wiki/64-bit#32_vs_64_bit
- http://java.sun.com/docs/hotspot/HotSpotFAQ.html#64bit_compilers
Dicho esto, al menos en mi máquina (Linux x86_64 con kernel de 64 bits), la versión HotSpot de 32 bits admite el modo cliente y servidor (a través de los indicadores -client y -server), pero el modo predeterminado es servidor, mientras que la versión de 64 bits solo admite modo servidor
Solo para señalar algunas soluciones:
Hay dos mecanismos que permiten una JVM de inicio más rápida. El primero, es el mecanismo de intercambio de datos de clase, que es compatible desde Java 6 Update 21 (solo con la máquina virtual cliente de HotSpot, y solo con el recolector de basura en serie, hasta donde yo sé)
Para activarlo, debe establecer -Xshare (en algunas implementaciones: -Xshareclasses ) las opciones de JVM.
Para leer más sobre la función, puede visitar: compartir datos de clase
El segundo mecanismo es un Java Quick Starter. Permite precargar clases durante el inicio del sistema operativo, ver: Java Quick Starter para más detalles.
Todas las máquinas virtuales con un sistema de tipo enriquecido como Java o CLR no serán instantáneas en comparación con los sistemas menos sofisticados como los que se encuentran en C o C ++. Esto se debe en gran medida a que están sucediendo muchas cosas en la VM, muchas clases se inicializan y son requeridas por un sistema en ejecución. Las instantáneas de un sistema inicializado ayudan, pero aún cuesta cargar esa imagen nuevamente en la memoria, etc.
Un mundo hello simple estilo una clase de trazador de líneas con un principal todavía requiere mucho para ser cargado e inicializado. La verificación de la clase requiere una gran cantidad de comprobación y validación de la dependencia, todo lo cual cuesta tiempo y se deben ejecutar muchas instrucciones de la CPU. Por otro lado, un programa en C no hará ninguna de estas e incluirá algunas instrucciones y luego invocará la función de la impresora.