Articulo de referencia

Rendimiento de Java

En el desarrollo de software , el lenguaje de programación Java se consideraba históricamente más lento que los lenguajes tipados de tercera generación más rápidos , como C y C+...

En el desarrollo de software , el lenguaje de programación Java se consideraba históricamente más lento que los lenguajes tipados de tercera generación más rápidos , como C y C++ . [ 1 ] A diferencia de estos lenguajes, Java se compila por defecto en una Máquina Virtual Java (JVM) con operaciones distintas a las del hardware real del ordenador. Las primeras implementaciones de JVM eran intérpretes ; simulaban las operaciones virtuales una por una en lugar de traducirlas a código máquina para su ejecución directa en el hardware.

Desde finales de la década de 1990, la velocidad de ejecución de los programas Java mejoró significativamente gracias a la introducción de la compilación justo a tiempo (JIT) (en 1997 para Java 1.1 ), [ 2 ] [ 3 ] [ 4 ] la adición de características del lenguaje que respaldan un mejor análisis de código y optimizaciones en la JVM (como HotSpot convirtiéndose en el predeterminado para la JVM de Sun en 2000). Las sofisticadas estrategias de recolección de basura también fueron un área de mejora. La ejecución de bytecode de Java por hardware, como la que ofrecía Jazelle de ARM , se exploró pero no se implementó.

El rendimiento de un programa Java compilado mediante bytecode depende de la óptima gestión de sus tareas por parte de la máquina virtual Java (JVM) del sistema, y ​​de la eficacia con la que la JVM aprovecha las características del hardware y del sistema operativo (SO) del ordenador. Por lo tanto, cualquier prueba o comparación de rendimiento de Java debe indicar siempre la versión, el proveedor, el SO y la arquitectura de hardware de la JVM utilizada. Del mismo modo, el rendimiento del programa equivalente compilado de forma nativa dependerá de la calidad de su código máquina generado, por lo que la prueba o comparación también debe indicar el nombre, la versión y el proveedor del compilador utilizado, así como las directivas de optimización del compilador activadas .

Métodos de optimización de máquinas virtuales

Con el tiempo, numerosas optimizaciones han mejorado el rendimiento de la JVM. Sin embargo, aunque Java fue a menudo la primera máquina virtual en implementarlas con éxito, también se han utilizado con frecuencia en otras plataformas similares.

Compilación justo a tiempo

Las primeras JVM siempre interpretaban los bytecodes de Java . Esto tenía una gran penalización de rendimiento de entre un factor de 10 y 20 para Java en comparación con C en aplicaciones promedio. [ 5 ] Para combatir esto, se introdujo un compilador justo a tiempo (JIT) en Java 1.1. Debido al alto costo de compilación, se introdujo un sistema adicional llamado HotSpot en Java 1.2 y se convirtió en el predeterminado en Java 1.3. Usando este marco, la máquina virtual de Java analiza continuamente el rendimiento del programa en busca de puntos críticos que se ejecutan con frecuencia o repetidamente. Estos luego son el objetivo de la optimización , lo que lleva a una ejecución de alto rendimiento con una sobrecarga mínima para el código menos crítico en términos de rendimiento. [ 6 ] [ 7 ] Algunos benchmarks muestran una ganancia de velocidad de 10 veces por este medio. [ 8 ] Sin embargo, debido a las restricciones de tiempo, el compilador no puede optimizar completamente el programa y, por lo tanto, el programa resultante es más lento que las alternativas de código nativo. [ 9 ] [ 10 ]

Optimización adaptativa

La optimización adaptativa es un método informático que realiza la recompilación dinámica de partes de un programa en función del perfil de ejecución actual. Con una implementación sencilla, un optimizador adaptativo puede simplemente encontrar un equilibrio entre la compilación justo a tiempo y la interpretación de instrucciones. En otro nivel, la optimización adaptativa puede aprovechar las condiciones locales de los datos para eliminar bifurcaciones y utilizar la expansión en línea.

Una máquina virtual Java como HotSpot también puede desoptimizar código previamente compilado con JIT. Esto permite realizar optimizaciones agresivas (y potencialmente inseguras), al tiempo que se puede desoptimizar el código posteriormente y volver a una ruta segura. [ 11 ] [ 12 ]

Recogida de basura

Las máquinas virtuales Java (JVM) 1.0 y 1.1 utilizaban un recolector de basura de marcado y barrido , que podía fragmentar el montón después de la recolección de basura. A partir de Java 1.2, las JVM cambiaron a un recolector generacional , que tiene un comportamiento de desfragmentación mucho mejor. [ 13 ] Las JVM modernas utilizan una variedad de métodos que han mejorado aún más el rendimiento de la recolección de basura . [ 14 ]

Otros métodos de optimización

Oops comprimido

La compresión de objetos permite que Java 5.0+ acceda a hasta 32 GB de memoria dinámica con referencias de 32 bits. Java no admite el acceso a bytes individuales, solo a objetos alineados a 8 bytes por defecto. Por ello, los 3 bits menos significativos de una referencia a memoria dinámica siempre serán 0. Al reducir la resolución de las referencias de 32 bits a bloques de 8 bytes, el espacio direccionable puede incrementarse hasta 32 GB. Esto reduce significativamente el uso de memoria en comparación con el uso de referencias de 64 bits, ya que Java utiliza referencias mucho más que otros lenguajes como C++. Java 8 admite alineaciones mayores, como la de 16 bytes, para admitir hasta 64 GB con referencias de 32 bits.

Verificación de código de bytes dividido

Antes de ejecutar una clase , la JVM de Sun verifica sus bytecodes Java (véase el verificador de bytecode ). Esta verificación se realiza de forma diferida: los bytecodes de las clases solo se cargan y verifican cuando la clase específica se carga y se prepara para su uso, y no al inicio del programa. Sin embargo, dado que las bibliotecas de clases Java también son clases Java regulares, deben cargarse cuando se utilizan, lo que significa que el tiempo de inicio de un programa Java suele ser mayor que el de los programas C++ , por ejemplo.

Un método llamado verificación en tiempo dividido , introducido por primera vez en la plataforma Java, Micro Edition (J2ME), se utiliza en la JVM desde la versión 6 de Java . Divide la verificación del código de bytes de Java en dos fases: [ 15 ]

  • Tiempo de diseño: al compilar una clase desde el código fuente a código de bytes.
  • Tiempo de ejecución: al cargar una clase.

En la práctica, este método funciona capturando el conocimiento que el compilador de Java tiene del flujo de clases y anotando los bytecodes de los métodos compilados con una sinopsis de la información del flujo de clases. Esto no simplifica considerablemente la verificación en tiempo de ejecución , pero sí permite algunos atajos.

Análisis de escape y ajuste de la cerradura

Java es capaz de gestionar la multihilo a nivel de lenguaje. La multihilo permite que los programas ejecuten varios procesos simultáneamente, mejorando así el rendimiento en sistemas informáticos con múltiples procesadores o núcleos. Además, una aplicación multihilo puede seguir respondiendo a las entradas, incluso mientras realiza tareas de larga duración.

Sin embargo, los programas que utilizan multihilo deben tener especial cuidado con los objetos compartidos entre hilos, bloqueando el acceso a los métodos o bloques compartidos cuando son utilizados por uno de los hilos. Bloquear un bloque o un objeto es una operación que consume mucho tiempo debido a la naturaleza de la operación subyacente a nivel del sistema operativo (véase control de concurrencia y granularidad de bloqueo ).

Dado que la biblioteca de Java desconoce qué métodos serán utilizados por más de un hilo, la biblioteca estándar siempre bloquea los bloques cuando es necesario en un entorno multihilo.

Antes de Java 6, la máquina virtual siempre bloqueaba objetos y bloques cuando el programa lo solicitaba, incluso si no existía riesgo de que un objeto fuera modificado por dos hilos diferentes a la vez. Por ejemplo, en este caso, una variable local Vectorse bloqueaba antes de cada una de las operaciones de suma para garantizar que no fuera modificada por otros hilos ( Vectorestá sincronizada), pero como es estrictamente local al método, esto es innecesario:

public String getNames () { final Vector < String > v = new Vector <> (); v . add ( "Me" ); v . add ( "You" ); v . add ( "Her" ); return v . toString (); }

A partir de Java 6, los bloques de código y los objetos se bloquean solo cuando es necesario, [ 16 ] por lo que en el caso anterior, la máquina virtual no bloquearía el objeto Vector en absoluto.

Desde la versión 6u23, Java incluye soporte para el análisis de escape. [ 17 ]

Mejoras en la asignación de registros

Antes de Java 6 , la asignación de registros era muy rudimentaria en la máquina virtual del cliente (no se compartían entre bloques ), lo que suponía un problema en los diseños de CPU con menos registros disponibles, como en los x86 . Si no hay más registros disponibles para una operación, el compilador debe copiar de un registro a la memoria (o de la memoria a un registro), lo que consume tiempo (el acceso a los registros es significativamente más rápido). Sin embargo, la máquina virtual del servidor utilizaba un asignador basado en gráficos de color y no presentaba este problema.

En el JDK 6 de Sun se introdujo una optimización de la asignación de registros; [ 18 ] entonces fue posible usar los mismos registros en diferentes bloques (cuando correspondía), reduciendo los accesos a la memoria. Esto dio como resultado una mejora del rendimiento de aproximadamente el 60 % en algunos benchmarks. [ 19 ]

Compartir datos de clase

El intercambio de datos de clase (denominado CDS por Sun) es un mecanismo que reduce el tiempo de inicio de las aplicaciones Java y también el consumo de memoria . Al instalar el JRE , el instalador carga un conjunto de clases del archivo JAR del sistema (el archivo JAR que contiene toda la biblioteca de clases Java, llamado rt.jar) en una representación interna privada y guarda dicha representación en un archivo denominado "archivo compartido". Durante las invocaciones posteriores de la JVM, este archivo compartido se asigna a la memoria , lo que ahorra el coste de cargar esas clases y permite que gran parte de los metadatos de la JVM para estas clases se compartan entre varios procesos de la JVM. [ 20 ]

La mejora correspondiente en el tiempo de inicio es más evidente para programas pequeños. [ 21 ]

Historial de mejoras de rendimiento

Además de las mejoras aquí enumeradas, cada versión de Java introdujo muchas mejoras de rendimiento en la JVM y en la interfaz de programación de aplicaciones (API) de Java.

JDK 1.1.6: Primera compilación justo a tiempo ( compilador JIT de Symantec ) [ 2 ] [ 22 ]

J2SE 1.2: Uso de un recolector generacional .

J2SE 1.3: Compilación justo a tiempo mediante HotSpot .

J2SE 1.4: Consulte aquí para obtener una descripción general de Sun sobre las mejoras de rendimiento entre las versiones 1.3 y 1.4.

Java SE 5.0: Compartición de datos de clase [ 23 ]

Java SE 6:

Otras mejoras:

  • Java OpenGL Mejoras en la velocidad de la canalización 2D de Java [ 24 ]
  • El rendimiento de Java 2D también mejoró significativamente en Java 6 [ 25 ].

Véase también 'Descripción general de Sun sobre las mejoras de rendimiento entre Java 5 y Java 6'. [ 26 ]

Java SE 6 Actualización 10

  • Java Quick Starter reduce el tiempo de inicio de la aplicación al precargar parte de los datos de JRE en el inicio del sistema operativo en la caché del disco . [ 27 ]
  • Las partes de la plataforma necesarias para ejecutar una aplicación a la que se accede desde la web cuando no está instalado JRE ahora se descargan primero. El JRE completo ocupa 12 MB; una aplicación Swing típica solo necesita descargar 4 MB para comenzar. Las partes restantes se descargan en segundo plano. [ 28 ]
  • El rendimiento gráfico en Windows mejoró al usar ampliamente Direct3D por defecto, [ 29 ] y usar sombreadores en la unidad de procesamiento gráfico (GPU) para acelerar operaciones complejas de Java 2D . [ 30 ]

Java 7

Se han publicado varias mejoras de rendimiento para Java 7: Se planean futuras mejoras de rendimiento para una actualización de Java 6 o Java 7: [ 31 ]

  • Proporcionar soporte de JVM para lenguajes de programación dinámicos , siguiendo el trabajo de prototipado que se está realizando actualmente en la máquina Da Vinci (Máquina Virtual Multilingüe), [ 32 ]
  • Mejorar la biblioteca de concurrencia existente mediante la gestión de la computación paralela en procesadores multinúcleo , [ 33 ] [ 34 ]
  • Permitir que la JVM utilice tanto el compilador JIT del cliente como el del servidor en la misma sesión con un método llamado compilación por niveles: [ 35 ]
    • El cliente se usaría en la fase de inicio (porque es bueno en la fase de inicio y para aplicaciones pequeñas),
    • El servidor se utilizaría para la ejecución a largo plazo de la aplicación (porque ofrece un rendimiento superior al del compilador del cliente para este fin).
  • Reemplazar el recolector de basura concurrente de baja pausa existente (también llamado recolector de marcado y barrido concurrente (CMS)) por un nuevo recolector llamado Garbage First (G1) para garantizar pausas consistentes a lo largo del tiempo. [ 36 ] [ 37 ]

Comparación con otros idiomas

Comparar objetivamente el rendimiento de un programa Java con el de uno equivalente escrito en otro lenguaje, como C++, requiere una herramienta de evaluación comparativa cuidadosamente diseñada que compare programas que realizan tareas idénticas. La plataforma de destino del compilador de bytecode de Java es la plataforma Java , y el bytecode es interpretado o compilado a código máquina por la JVM. Otros compiladores casi siempre se dirigen a una plataforma de hardware y software específica, produciendo código máquina que permanece prácticamente inalterado durante la ejecución . Estos dos enfoques distintos dan lugar a escenarios muy diferentes y difíciles de comparar: compilaciones y recompilaciones estáticas frente a dinámicas , la disponibilidad de información precisa sobre el entorno de ejecución, entre otros.

Java suele compilarse justo a tiempo en tiempo de ejecución por la máquina virtual de Java , pero también puede compilarse con antelación , al igual que C++. Cuando se compila justo a tiempo, los microbenchmarks de The Computer Language Benchmarks Game indican lo siguiente sobre su rendimiento: [ 38 ]

  • más lento que los lenguajes compilados como C o C++ , [ 39 ]
  • similar a otros lenguajes compilados justo a tiempo como C# , [ 40 ]
  • mucho más rápido que los lenguajes sin un compilador de código nativo efectivo ( JIT o AOT ), como Perl , Ruby , PHP y Python . [ 41 ]

Velocidad del programa

Los benchmarks suelen medir el rendimiento de programas pequeños con alta carga computacional. En algunos programas reales, Java supera a C. Un ejemplo es el benchmark de Jake2 (un clon de Quake II escrito en Java mediante la traducción del código C original bajo licencia GPL ). La versión de Java 5.0 ofrece un mejor rendimiento en algunas configuraciones de hardware que su contraparte en C. [ 42 ] Si bien no se especifica cómo se midieron los datos (por ejemplo, si se utilizó el ejecutable original de Quake II compilado en 1997, lo cual podría considerarse deficiente, ya que los compiladores de C actuales podrían lograr mejores optimizaciones para Quake), se observa cómo el mismo código fuente de Java puede experimentar un enorme aumento de velocidad simplemente actualizando la máquina virtual, algo imposible de lograr con un enfoque completamente estático.

Para otros programas, la contraparte en C++ puede, y generalmente lo hace, ejecutarse significativamente más rápido que su equivalente en Java. Una prueba de rendimiento realizada por Google en 2011 mostró una diferencia de un factor de 10 entre C++ y Java. [ 43 ] En el otro extremo, una prueba de rendimiento académica realizada en 2012 con un algoritmo de modelado 3D mostró que la JVM de Java 6 era entre 1,09 y 1,91 veces más lenta que C++ en Windows. [ 44 ]

Algunas optimizaciones que son posibles en Java y lenguajes similares pueden no ser posibles en ciertas circunstancias en C++: [ 45 ]

  • El uso de punteros al estilo C puede dificultar la optimización en lenguajes que admiten punteros,
  • El uso de métodos de análisis de escape es limitado en C++ , por ejemplo, porque un compilador de C++ no siempre sabe si un objeto será modificado en un bloque de código dado debido a los punteros , [ nota 1 ]
  • Java puede acceder a los métodos de instancia derivados más rápidamente que C++ a los métodos virtuales derivados debido a la búsqueda adicional en la tabla virtual de C++. Sin embargo, los métodos no virtuales en C++ no sufren cuellos de botella de rendimiento relacionados con la tabla virtual y, por lo tanto, presentan un rendimiento similar al de Java.

La JVM también es capaz de realizar optimizaciones específicas del procesador o expansión en línea . Además, la capacidad de desoptimizar código ya compilado o expandido en línea a veces le permite realizar optimizaciones más agresivas que las realizadas por lenguajes de tipado estático cuando intervienen funciones de bibliotecas externas. [ 46 ] [ 47 ]

Los resultados de las micropruebas comparativas entre Java y C++ dependen en gran medida de las operaciones que se comparen. Por ejemplo, al comparar con Java 5.0:


Notas
  1. Este tipo de conflictos pueden mitigarse en programas C++ a nivel de código fuente mediante el uso de métodos avanzados como asignadores personalizados , aprovechando precisamente el tipo de complejidad de codificación de bajo nivel que Java fue diseñado para ocultar y encapsular; sin embargo, este enfoque rara vez es práctico si no se adopta (o al menos se prevé) mientras el programa se encuentra en fase de desarrollo principal.

Rendimiento multinúcleo

La escalabilidad y el rendimiento de las aplicaciones Java en sistemas multinúcleo están limitados por la tasa de asignación de objetos. Este efecto se conoce a veces como "pared de asignación". [ 54 ] Sin embargo, en la práctica, los algoritmos modernos de recolección de basura utilizan múltiples núcleos para realizar la recolección, lo que en cierta medida alivia este problema. Se ha informado que algunos recolectores de basura soportan tasas de asignación superiores a un gigabyte por segundo, [ 55 ] y existen sistemas basados ​​en Java que no tienen problemas para escalar a varios cientos de núcleos de CPU y montones de varios cientos de GB. [ 56 ]

La gestión automática de memoria en Java permite un uso eficiente de estructuras de datos inmutables y sin bloqueo, cuya implementación resulta extremadamente difícil, o incluso imposible, sin algún tipo de recolección de basura. Java ofrece varias de estas estructuras de alto nivel en su biblioteca estándar, en el paquete java.util.concurrent, mientras que muchos lenguajes utilizados históricamente para sistemas de alto rendimiento, como C o C++, aún carecen de ellas.

Tiempo de inicio

El tiempo de inicio de Java suele ser mucho más lento que el de muchos otros lenguajes, como C , C++ , Perl o Python , porque muchas clases (y, sobre todo, las clases de las bibliotecas de clases de la plataforma ) deben cargarse antes de poder utilizarse.

En comparación con entornos de ejecución populares similares, para programas pequeños que se ejecutan en una máquina Windows, el tiempo de inicio parece ser similar al de Mono y un poco más lento que el de .NET . [ 57 ]

Parece que gran parte del tiempo de inicio se debe a operaciones de entrada/salida (E/S) en lugar de a la inicialización de la JVM o la carga de clases (el archivo de datos de clase rt.jar por sí solo ocupa 40 MB y la JVM debe buscar muchos datos en este archivo grande). [ 27 ] Algunas pruebas mostraron que, si bien el nuevo método de verificación de bytecode dividido mejoró la carga de clases en aproximadamente un 40 %, solo logró una mejora de inicio de alrededor del 5 % para programas grandes. [ 58 ]

Si bien se trata de una pequeña mejora, es más visible en programas pequeños que realizan una operación simple y luego finalizan, ya que la carga de datos de la plataforma Java puede representar muchas veces la carga de la operación real del programa.

A partir de Java SE 6 Update 10, el JRE de Sun incluye una herramienta de inicio rápido que precarga los datos de clase al arrancar el sistema operativo para obtener los datos de la caché del disco en lugar de hacerlo directamente del disco.

Excelsior JET aborda el problema desde otra perspectiva. Su optimizador de inicio reduce la cantidad de datos que deben leerse del disco al iniciar la aplicación y hace que las lecturas sean más secuenciales.

En noviembre de 2004, se lanzó públicamente Nailgun , un "cliente, protocolo y servidor para ejecutar programas Java desde la línea de comandos sin incurrir en la sobrecarga de inicio de la JVM". [ 59 ] Introdujo por primera vez una opción para que los scripts usaran una JVM como demonio , para ejecutar una o más aplicaciones Java sin la sobrecarga de inicio de la JVM. El demonio Nailgun es inseguro: "todos los programas se ejecutan con los mismos permisos que el servidor". Cuando se necesita seguridad multiusuario , Nailgun es inapropiado sin precauciones especiales. Los scripts donde el inicio de la JVM por aplicación domina el uso de recursos, ven mejoras en el rendimiento de tiempo de ejecución de uno a dos órdenes de magnitud . [ 60 ]

Uso de la memoria

El uso de memoria de Java es mucho mayor que el de C++ porque:

  • En Java, existe una sobrecarga de 8 bytes por cada objeto y de 12 bytes por cada matriz [ 61 ] . Si el tamaño de un objeto no es múltiplo de 8 bytes, se redondea al siguiente múltiplo de 8. Esto significa que un objeto que contiene un campo de un byte ocupa 16 bytes y necesita una referencia de 4 bytes. C++ también asigna un puntero (generalmente de 4 u 8 bytes) para cada objeto cuya clase declara funciones virtuales , directa o indirectamente . [ 62 ]
  • La falta de aritmética de direcciones hace que la creación de contenedores eficientes en memoria, como estructuras con espaciado reducido y listas enlazadas XOR , sea actualmente imposible ( el proyecto OpenJDK Valhalla pretende mitigar estos problemas, aunque no pretende introducir aritmética de punteros; esto no se puede hacer en un entorno con recolección de basura).
  • A diferencia de malloc y new, la sobrecarga de rendimiento promedio de la recolección de basura se acerca asintóticamente a cero (más precisamente, a un ciclo de CPU) a medida que aumenta el tamaño del montón. [ 63 ]
  • Partes de la biblioteca de clases de Java deben cargarse antes de la ejecución del programa (al menos las clases utilizadas dentro de un programa). [ 64 ] Esto genera una sobrecarga de memoria significativa para aplicaciones pequeñas.
  • Tanto la recompilación del binario de Java como la del código nativo normalmente se realizarán en memoria.
  • La máquina virtual utiliza una cantidad considerable de memoria.
  • En Java, un objeto compuesto (una clase A que utiliza instancias de B y C) se crea mediante referencias a instancias asignadas de B y C. En C++, el coste en memoria y rendimiento de este tipo de referencias se puede evitar cuando la instancia de B y/o C existe dentro de A.

En la mayoría de los casos, una aplicación C++ consumirá menos memoria que una aplicación Java equivalente debido a la gran sobrecarga de la máquina virtual de Java, la carga de clases y el redimensionamiento automático de memoria. Para programas en los que la memoria es un factor crítico a la hora de elegir entre lenguajes y entornos de ejecución, es necesario realizar un análisis de costo-beneficio.

funciones trigonométricas

El rendimiento de las funciones trigonométricas es malo en comparación con C, porque Java tiene especificaciones estrictas para los resultados de las operaciones matemáticas, que pueden no corresponderse con la implementación de hardware subyacente. [ 65 ] En el subconjunto de punto flotante x87 , Java desde la versión 1.4 realiza la reducción de argumentos para seno y coseno en software, [ 66 ] causando una gran pérdida de rendimiento para valores fuera del rango. [ 67 ]

Interfaz nativa de Java

La Interfaz Nativa de Java (JNI ) genera una sobrecarga elevada, lo que dificulta cruzar el límite entre el código que se ejecuta en la JVM y el código nativo. [ 68 ] [ 69 ] [ 70 ] El Acceso Nativo de Java (JNA) proporciona a los programas Java un acceso sencillo a las bibliotecas compartidas nativas ( bibliotecas de vínculos dinámicos (DLL) en Windows) únicamente mediante código Java, sin JNI ni código nativo. Esta funcionalidad es comparable a Platform/Invoke de Windows y ctypes de Python . El acceso es dinámico en tiempo de ejecución sin generación de código. Sin embargo, tiene un coste, y JNA suele ser más lento que JNI. [ 71 ]

Interfaz de usuario

Swing se ha considerado más lento que los kits de herramientas de widgets nativos , ya que delega la representación de widgets a la API 2D pura de Java . Sin embargo, las pruebas comparativas que comparan el rendimiento de Swing con el Kit de herramientas de widgets estándar , que delega la representación a las bibliotecas GUI nativas del sistema operativo, no muestran un claro ganador, y los resultados dependen en gran medida del contexto y los entornos. [ 72 ] Además, el nuevo framework JavaFX , diseñado para reemplazar a Swing, aborda muchos de los problemas inherentes de Swing.

Uso para computación de alto rendimiento

Algunas personas creen que el rendimiento de Java para la computación de alto rendimiento (HPC) es similar al de Fortran en pruebas de rendimiento intensivas en cómputo, pero que las JVM todavía tienen problemas de escalabilidad para realizar comunicaciones intensivas en una red de computación en malla . [ 73 ]

Sin embargo, las aplicaciones de computación de alto rendimiento escritas en Java han ganado competiciones de evaluación comparativa. En 2008, [ 74 ] y 2009, [ 75 ] [ 76 ] un clúster basado en Apache Hadoop (un proyecto de computación de alto rendimiento de código abierto escrito en Java) fue capaz de ordenar un terabyte y un petabyte de enteros más rápidamente. Sin embargo, la configuración de hardware de los sistemas participantes no era fija. [ 77 ] [ 78 ]

En concursos de programación

Los programas en Java se inician más lentamente que los de otros lenguajes compilados. [ 79 ] [ 80 ] Por lo tanto, algunos sistemas de evaluación en línea, especialmente los alojados por universidades chinas, utilizan límites de tiempo más largos para los programas Java [ 81 ] [ 82 ] [ 83 ] [ 84 ] [ 85 ] para ser justos con los concursantes que utilizan Java.

Véase también

Citas

  1. "Comparativas de rendimiento entre Java y C++" .
  2. 1 2 "El compilador Java Just-In-Time de Symantec se integrará en Sun JDK 1.1" . Archivado del original el 28 de junio de 2010.
  3. "Breve análisis: Apple adquiere la licencia del compilador justo a tiempo de Symantec" . cnet.com. 12 de mayo de 1998. Consultado el 15 de noviembre de 2015 .
  4. "Java se vuelve cuatro veces más rápido con el nuevo compilador Just-In-Time de Symantec" .{{cite web}}: CS1 maint: servicio de archivado obsoleto ( enlace )
  5. "Comparación de rendimiento de entornos de ejecución Java/.NET (octubre de 2004)" .
  6. Kawaguchi, Kohsuke (30 de marzo de 2008). "Análisis profundo del código ensamblador desde Java" . Archivado del original el 2 de abril de 2008. Recuperado el 2 de abril de 2008 .
  7. "Generación de código rápida y eficaz en un compilador Java Just-In-Time" (PDF) . Intel Corporation . Consultado el 22 de junio de 2007 .
  8. Este artículo muestra que la mejora en el rendimiento entre el modo interpretado y Hotspot asciende a más de un factor de 10.
  9. Rendimiento numérico en C, C# y Java
  10. Comparación del rendimiento algorítmico entre los lenguajes de programación C, C++, Java y C#. Archivado el 31 de marzo de 2010 en Wayback Machine .
  11. "La máquina virtual Java HotSpot, v1.4.1" . Sun Microsystems . Consultado el 20 de abril de 2008 .
  12. Nutter, Charles (28 de enero de 2008). "Lang.NET 2008: Reflexiones del primer día" . Recuperado el 18 de enero de 2011. La desoptimización es muy emocionante cuando se trata de problemas de rendimiento, ya que significa que puedes hacer optimizaciones mucho más agresivas... sabiendo que podrás recurrir a un camino seguro y probado más adelante.
  13. Biblioteca IBM DeveloperWorks
  14. Por ejemplo, la duración de las pausas es menos perceptible ahora. Vea, por ejemplo, este clon de Quake II escrito en Java: Jake2 .
  15. "Nueva característica de Java SE 6: Verificador de comprobación de tipos" . Java.net . Consultado el 18 de enero de 2011 .
  16. Brian Goetz (18 de octubre de 2005). "Teoría y práctica de Java: optimizaciones de sincronización en Mustang" . IBM . Consultado el 26 de enero de 2013 .
  17. " Mejoras de rendimiento de la máquina virtual Java HotSpot" . Oracle Corporation . Consultado el 14 de enero de 2014. El análisis de escape es una técnica mediante la cual el compilador del servidor Java HotSpot puede analizar el alcance de los usos de un nuevo objeto y decidir si asignarlo en el montón de Java. El análisis de escape es compatible y está habilitado de forma predeterminada en Java SE 6u23 y versiones posteriores.
  18. Informe de error: nuevo asignador de registros, corregido en Mustang (JDK 6) b59
  19. ↑ ¡ El cliente HotSpot de Mustang es un 58 % más rápido! Archivado el 5 de marzo de 2012 en Wayback Machine , en el blog de Osvaldo Pinali Doederlein en java.net.
  20. Compartición de datos de clase en java.sun.com
  21. Compartición de datos de clase en JDK 1.5.0 en el foro Java Buzz de artima developer
  22. Mckay, Niali. "Java se vuelve cuatro veces más rápido con el nuevo compilador just-in-time de Symantec" .
  23. Resumen de Sun sobre las mejoras de rendimiento entre las versiones 1.4 y 5.0.
  24. STR-Crazier: Mejoras de rendimiento en Mustang. Archivado el 5 de enero de 2007 en Wayback Machine , en el blog de Chris Campbell en java.net.
  25. Consulte aquí una comparativa que muestra una mejora del rendimiento de aproximadamente un 60 % al pasar de Java 5.0 a Java 6 para la aplicación JFreeChart.
  26. Documento técnico sobre el rendimiento de Java SE 6 en http://java.sun.com
  27. 1 2 Haase, Chet (mayo de 2007). "Consumer JRE: Tecnología Java más ágil y eficiente" . Sun Microsystems . Recuperado el 27 de julio de 2007. A nivel del sistema operativo, todos estos megabytes deben leerse del disco, lo cual es una operación muy lenta. En realidad, es el tiempo de búsqueda del disco lo que resulta problemático; leer archivos grandes de forma secuencial es relativamente rápido, pero buscar los bits que realmente necesitamos no lo es. Por lo tanto, aunque solo necesitamos una pequeña fracción de los datos en estos archivos grandes para cualquier aplicación en particular, el hecho de que estemos buscando por todo el contenido de los archivos significa que hay mucha actividad en el disco.
  28. Haase, Chet (mayo de 2007). "Consumer JRE: Tecnología Java más ágil y eficiente" . Sun Microsystems . Consultado el 27 de julio de 2007 .
  29. Haase, Chet (mayo de 2007). "Consumer JRE: Tecnología Java más ágil y eficiente" . Sun Microsystems . Consultado el 27 de julio de 2007 .
  30. Campbell, Chris (7 de abril de 2007). "Java 2D más rápido mediante sombreadores" . Archivado del original el 5 de junio de 2011. Recuperado el 18 de enero de 2011 .
  31. Haase, Chet (mayo de 2007). "Consumer JRE: Tecnología Java más ágil y eficiente" . Sun Microsystems . Consultado el 27 de julio de 2007 .
  32. "JSR 292: Compatibilidad con lenguajes de tipado dinámico en la plataforma Java" . jcp.org . Consultado el 28 de mayo de 2008 .
  33. Goetz, Brian (4 de marzo de 2008). "Teoría y práctica de Java: Se acabó, Parte 2" . IBM . Consultado el 9 de marzo de 2008 .
  34. Lorimer, RJ (21 de marzo de 2008). "Paralelismo con Fork/Join en Java 7" . infoq.com . Consultado el 28 de mayo de 2008 .
  35. "Nuevas optimizaciones del compilador en la máquina virtual Java HotSpot" (PDF) . Sun Microsystems. Mayo de 2006. Consultado el 30 de mayo de 2008 .
  36. Humble, Charles (13 de mayo de 2008). "JavaOne: Primero la basura" . infoq.com . Consultado el 7 de septiembre de 2008 .
  37. Coward, Danny (12 de noviembre de 2008). "Java VM: Probando un nuevo recolector de basura para JDK 7" . Archivado del original el 8 de diciembre de 2011. Recuperado el 15 de noviembre de 2008 .
  38. "Computer Language Benchmarks Game" . benchmarksgame.alioth.debian.org. Archivado del original el 25 de enero de 2015. Consultado el 2 de junio de 2011 .
  39. "Juego de evaluación comparativa de lenguajes informáticos" . benchmarksgame.alioth.debian.org. Archivado del original el 13 de enero de 2015. Consultado el 2 de junio de 2011 .
  40. "Computer Language Benchmarks Game" . benchmarksgame.alioth.debian.org. Archivado del original el 10 de enero de 2015. Consultado el 2 de junio de 2011 .
  41. "Computer Language Benchmarks Game" . benchmarksgame.alioth.debian.org. Archivado del original el 2 de enero de 2015. Recuperado el 2 de junio de 2011 .
  42. 260/250 fotogramas/s frente a 245 fotogramas/s (ver prueba comparativa )
  43. Hundt, Robert. "Reconocimiento de bucles en C++/Java/Go/Scala" (PDF) . Scala Days 2011. Stanford, California . Consultado el 23 de marzo de 2014 .
  44. L. Gherardi; D. Brugali; D. Comotti (2012). "Una evaluación del rendimiento de Java frente a C++: una prueba comparativa de modelado 3D" (PDF) . Universidad de Bérgamo . Recuperado el 23 de marzo de 2014. Utilizando el compilador Server, que está mejor optimizado para aplicaciones de larga duración, se ha demostrado que Java es entre 1,09 y 1,91 veces más lento (...). En conclusión, los resultados obtenidos con el compilador Server y estas características importantes sugieren que Java puede considerarse una alternativa válida a C++.
  45. Lewis, JP; Neumann, Ulrich. "Rendimiento de Java frente a C++" . Laboratorio de Gráficos por Computadora y Tecnología Inmersiva, Universidad del Sur de California.
  46. "El motor de rendimiento Java HotSpot: ejemplo de inserción de métodos" . Oracle Corporation . Consultado el 11 de junio de 2011 .
  47. Nutter, Charles (3 de mayo de 2008). "El poder de la JVM" . Recuperado el 11 de junio de 2011. ¿ Qué sucede si ya has insertado el método de A cuando llega B? Aquí, una vez más, la JVM brilla. Debido a que la JVM es esencialmente un entorno de ejecución de lenguaje dinámico en su interior, permanece siempre vigilante, observando precisamente este tipo de eventos. Y aquí está la parte realmente genial: cuando las situaciones cambian, la JVM puede desoptimizar. Este es un detalle crucial. Muchos otros entornos de ejecución solo pueden hacer su optimización una vez. Los compiladores de C deben hacerlo todo por adelantado, durante la compilación. Algunos permiten perfilar la aplicación y alimentarla a compilaciones posteriores, pero una vez que se ha publicado un fragmento de código, está esencialmente tan optimizado como nunca lo estará. Otros sistemas similares a máquinas virtuales, como el CLR, tienen una fase JIT, pero ocurre al principio de la ejecución (quizás incluso antes de que el sistema comience a ejecutarse) y nunca vuelve a ocurrir. La capacidad de la JVM para desoptimizar y volver a la interpretación le da margen para ser optimista... margen para hacer conjeturas ambiciosas y volver con elegancia a un estado seguro, para intentarlo de nuevo más tarde.
  48. "Microbenchmarking C++, C# y Java: aritmética de enteros de 32 bits" . Dr. Dobb's Journal . 1 de julio de 2005. Consultado el 18 de enero de 2011 .
  49. "Microbenchmarking C++, C# y Java: aritmética de doble precisión de 64 bits" . Dr. Dobb's Journal . 1 de julio de 2005. Consultado el 18 de enero de 2011 .
  50. "Microbenchmarking C++, C# y Java: E/S de archivos" . Dr. Dobb's Journal . 1 de julio de 2005. Consultado el 18 de enero de 2011 .
  51. "Microbenchmarking C++, C# y Java: Excepción" . Dr. Dobb's Journal . 1 de julio de 2005. Consultado el 18 de enero de 2011 .
  52. "Microbenchmarking C++, C# y Java: Array" . Dr. Dobb's Journal . 1 de julio de 2005. Consultado el 18 de enero de 2011 .
  53. "Microbenchmarking C++, C# y Java: funciones trigonométricas" . Dr. Dobb's Journal . 1 de julio de 2005. Consultado el 18 de enero de 2011 .
  54. Yi Zhao, Jin Shi, Kai Zheng, Haichuan Wang, Haibo Lin y Ling Shao, Muro de asignación: un factor limitante de las aplicaciones Java en plataformas multinúcleo emergentes , Actas de la 24.ª conferencia ACM SIGPLAN sobre sistemas, lenguajes y aplicaciones de programación orientada a objetos, 2009.
  55. "C4: El recolector de compactación concurrente continuo" (PDF) . Archivado del original (PDF) el 9 de agosto de 2014. Recuperado el 29 de octubre de 2013 .
  56. Azul intimida a Java con una máquina de 768 núcleos
  57. "Prueba comparativa del rendimiento del sistema y del arranque para .Net, Mono, Java, C++ y sus respectivas interfaces de usuario" . 2 de septiembre de 2010.
  58. "¿Qué tan rápido es el nuevo verificador?" . 7 de febrero de 2006. Archivado del original el 16 de mayo de 2006. Recuperado el 9 de mayo de 2007 .
  59. Pistola de clavos
  60. La página de fondo de Nailgun demuestra una aceleración en el " mejor de los casos " de 33 veces (para programas "Hola, mundo" con script , es decir, programas de corta duración).
  61. "Cómo calcular el uso de memoria de los objetos Java" .
  62. "InformIT: Guía de referencia de C++ > el modelo de objetos" . Archivado del original el 21 de febrero de 2008. Consultado el 22 de junio de 2009 .
  63. https://www.youtube.com/watch?v=M91w0SBZ-wc  : Entendiendo la recolección de basura de Java: una charla de Gil Tene en JavaOne
  64. ".: ToMMTi-Systems :: Hinter den Kulissen hardware 3D más moderno" . 
  65. "Math (Java Platform SE 6)" . Sun Microsystems . Consultado el 8 de junio de 2008 .
  66. Gosling, James (27 de julio de 2005). "Meditación trascendental" . Archivado del original el 12 de agosto de 2011. Recuperado el 8 de junio de 2008 .
  67. Cowell-Shah, Christopher W. (8 de enero de 2004). "Resumen del rendimiento de nueve lenguajes: evaluación comparativa de operaciones matemáticas y E/S de archivos" . Archivado del original el 11 de octubre de 2018. Recuperado el 8 de junio de 2008 .
  68. Wilson, Steve; Jeff Kesselman (2001). "Rendimiento de la plataforma Java™: Uso de código nativo" . Sun Microsystems . Recuperado el 15 de febrero de 2008 .
  69. Kurzyniec, Dawid; Vaidy Sunderam. "Cooperación eficiente entre Java y códigos nativos: evaluación comparativa del rendimiento de JNI" (PDF) . Archivado del original (PDF) el 14 de febrero de 2005. Recuperado el 15 de febrero de 2008 .
  70. Bloch 2018 , pág. 285, Capítulo §11 Punto 66: Utilice los métodos nativos con criterio.
  71. "¿Cómo se compara el rendimiento de JNA con el de JNI personalizado?" . Sun Microsystems . Consultado el 26 de diciembre de 2009 .
  72. Igor, Križnar (10 de mayo de 2005). "Comparación de rendimiento entre SWT y Swing" (PDF) . cosylab.com. Archivado del original (PDF) el 4 de julio de 2008. Consultado el 24 de mayo de 2008. Es difícil establecer una regla general sobre dónde SWT superaría a Swing, o viceversa. En algunos entornos (por ejemplo, Windows), SWT es superior. En otros (Linux, VMware con Windows), Swing y su optimización de redibujado superan significativamente a SWT. Las diferencias de rendimiento son significativas: factores de 2 o más son comunes, en cualquier dirección.
  73. Brian Amedro; Vladimir Bodnartchouk; Denis Caromel; Christian Delbe; Fabrice Huet; Guillermo L. Taboada (agosto de 2008). "Estado actual de Java para HPC" . INRIA . Recuperado el 9 de septiembre de 2008. Primero realizamos algunos microbenchmarks para varias JVM, mostrando el buen rendimiento general para operaciones aritméticas básicas (...). Comparando esta implementación con una Fortran/MPI, mostramos que tienen un rendimiento similar en benchmarks de computación intensiva, pero aún tienen problemas de escalabilidad cuando realizan comunicaciones intensivas.
  74. Owen O'Malley - Equipo de Computación en Red de Yahoo! (julio de 2008). "Apache Hadoop gana la prueba de rendimiento de ordenación de terabytes" . Archivado del original el 15 de octubre de 2009. Consultado el 21 de diciembre de 2008. Esta es la primera vez que un programa Java o de código abierto ha ganado.
  75. "Hadoop ordena un petabyte en 16,25 horas y un terabyte en 62 segundos" . CNET.com . 11 de mayo de 2009. Archivado del original el 16 de mayo de 2009. Recuperado el 8 de septiembre de 2010. Los detalles del hardware y del sistema operativo son: (...) Sun Java JDK (1.6.0_05-b13 y 1.6.0_13-b03) (32 y 64 bits)
  76. "Hadoop bate récords mundiales de clasificación de datos" . CNET.com . 15 de mayo de 2009. Consultado el 8 de septiembre de 2010 .
  77. Chris Nyberg; Mehul Shah. "Página principal de Sort Benchmark" . Consultado el 30 de noviembre de 2010 .
  78. ^ Czajkowski, Grzegorz (21 de noviembre de 2008). "Clasificación de 1 PB con MapReduce" . Consultado el 1 de diciembre de 2010 .
  79. "TCO10" . Archivado del original el 18 de octubre de 2010. Consultado el 21 de junio de 2010 .
  80. "Cómo escribir soluciones Java en Timus Online Judge" .
  81. "Preguntas frecuentes" .
  82. "Preguntas frecuentes | Juez en línea TJU ACM-ICPC" . Archivado del original el 29 de junio de 2010. Consultado el 25 de mayo de 2010 .
  83. "Preguntas frecuentes | CodeChef" .
  84. "Página principal del Juez en línea de la Universidad de Xidian" . Archivado del original el 19 de febrero de 2012. Consultado el 13 de noviembre de 2011 .
  85. "Preguntas frecuentes" .

Referencias

  • Bloch, Joshua (2018). «Java eficaz: Guía del lenguaje de programación» (tercera  ed.). Addison-Wesley. ISBN 978-0134685991.
  • Sitio web dedicado a información sobre el rendimiento de Java.
  • Depuración de problemas de rendimiento de Java
  • Portal de rendimiento de Java de Sun
  • Mapa mental basado en presentaciones de ingenieros de la sucursal de Oracle en San Petersburgo (como imagen PNG grande).