2009-05-09 22 views
49

¿Qué hace que la JVM (en particular, la implementación de Sun) funcione lentamente 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.¿Por qué es lenta la JVM para comenzar?

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?

+1

Etiquetado con subjetivo. "Lento" es una descripción subjetiva. –

+20

@Martin OConnor: "lento" es subjetivo, pero esta pregunta no lo es. – Zifre

+1

AFAIK, el motor de Javascript V8 de Google para Node.js tarda unos 30 milisegundos. Dudo que sea mucho más lento que la JVM. Parece que la JVM tarda unos 70 ms. http://tinyurl.com/phkwn45 –

Respuesta

18

Aquí está what Wikipedia has to say on the issue (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).

+0

Gracias, el artículo de Sun que vincula tiene algunos buenos detalles. – Jegschemesch

+1

Una aclaración: no es solo (o quizás tanto) E/S de disco, sino que busca clases desde dentro de jar (wars, ears), que son archivos zip. La extracción lleva CPU, pero especialmente si están comprimidos. – StaxMan

+3

El tiempo de CPU para descomprimir es mínimo. De hecho, stackoverflow utiliza la compresión como una optimización del rendimiento, y la compresión es masiva que las descompresiones. –

1

Hay una serie de razones:

  • un montón de jar s para cargar
  • verificación (hacer el código seguro de no hacer cosas malas)
  • JIT (compilación en tiempo de ejecución) por encima

No estoy seguro acerca 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.

+0

Las clases compiladas con -destino 1.6 son mucho más rápidas de verificar (el verificador Harmony también es mucho más rápido). –

+1

CPython compila archivos Python en bytecode antes de ejecutarlos, como Java. –

+0

@Bastien: hay una gran diferencia entre el código de bytes y el código de máquina. El bytecode compuesto es * mucho * más fácil que generar código de máquina. – Zifre

5

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.

+3

Sea cual sea la condición, jvm sigue siendo el vm que tiene el inicio más lento. Puede encontrarlo lo suficientemente rápido en cierto grado de máquina y para cierto tamaño de aplicación. Pero aún así, su tiempo de inicio es indiscutiblemente lento. – Sake

+0

Creo que las aplicaciones de GUI son principalmente lo que le dio a Java la impresión de ser lenta ... tener que cargar un montón de clases AWT y Swing es, probablemente, lo que hace que tome al menos un segundo. – Andy

4

Si está utilizando Sun's HotSpot para x86_64 (64 bits compilados), 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 la CPU, pero tiene tiempos de arranque más rápidos.

Véase, por ejemplo:

Dicho esto, al menos en mi máquina (x86_64 Linux con núcleo de 64 bits), la versión de 32 bits HotSpot soporta tanto el cliente como modo de servidor (a través de los indicadores -client y -server), pero por defecto está en el modo de servidor, mientras que la versión de 64 bits solo es compatible con el modo de servidor.

+0

¿Estás seguro de que tu información es correcta: no he oído hablar de una (moderna) Sun JVM que hiciera JIT completo para todas las clases? Y el modo servidor definitivamente NO lo hace en la mayoría de los sistemas. La diferencia entre los modos cliente y servidor tiene más que ver con diferentes configuraciones, como el umbral utilizado para la alineación de JIT. – StaxMan

+0

Server HotSpot no hace compilación hasta 10,000 iteraciones. El cliente lo hace a las 1,500. Sin embargo, el servidor se implementa de forma algo diferente (dos en lugar de una representación intermedia, IIRC). –

1

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. Muchas optimizaciones se realizan 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.

+3

(3 años demasiado tarde) ¡Puede hacerlo, con una herramienta como Nailgun! – slezica

3

Realmente depende de lo que esté 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 (< < 0.001 Sra).

+3

un estudio sobre el tiempo de arranque de JVM: http://tinyurl.com/phkwn45 –

+2

@AlexMills Vale la pena señalar que estos investigadores usaron una máquina de 2006. Un i3-4370 de doble núcleo podría ser 4-5 veces más rápido. Sin embargo, es probable que su análisis sea actual. –

+0

tal vez, pero supongo que solo un núcleo es responsable de cargar la JVM. Apuesto que una SSD vs HDD haría más la diferencia. –

0

Todas las máquinas virtuales con un sistema de tipo enriquecido como Java o CLR no serán instantáneas en comparación con 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 de nuevo en la memoria, etc.

Una clase de liner simple de estilo único hola con un main aún requiere que se cargue e inicialice mucho. 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.

6

para notar algunas soluciones:

Existen dos mecanismos que permiten a JVM inicio más rápido. El primero, es el mecanismo de intercambio de datos de clase, que es compatible desde Java 6 Update 21 (solo con HotSpot Client VM, y solo con el recolector de basura en serie hasta donde yo sé)

Para activarlo necesita para establecer -Xshare (en algunas implementaciones: -Xshareclasses) Opciones de JVM.

Para leer más sobre la función que puede visitar: Class data sharing

El segundo mecanismo es un arranque rápido de Java. Permite precargar clases durante el arranque del sistema operativo, ver: Java Quick Starter para más detalles.

Cuestiones relacionadas