En el desarrollo de software , el lenguaje de programación Java se consideró históricamente más lento que los lenguajes de escritura de tercera generación más rápidos , como C y C ++ . [1] La razón principal es un diseño de lenguaje diferente, donde después de la compilación, los programas Java se ejecutan en una máquina virtual Java (JVM) en lugar de directamente en el procesador de la computadora como código nativo , como lo hacen los programas C y C ++. El rendimiento era un motivo de preocupación porque gran parte del software empresarial se escribió en Java después de que el lenguaje se popularizara rápidamente a fines de la década de 1990 y principios de la de 2000.
Desde finales de la década de 1990, la velocidad de ejecución de los programas Java mejoró significativamente mediante 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 de lenguaje que soportan un mejor código análisis y optimizaciones en la JVM (como HotSpot que se convirtió en el predeterminado para la JVM de Sun en 2000). También se exploró la ejecución de hardware del código de bytes de Java, como el ofrecido por Jazelle de ARM , para ofrecer mejoras significativas en el rendimiento.
El rendimiento de un programa Java compilado con código de bytes de Java depende de qué tan óptimamente sean administradas sus tareas asignadas por la máquina virtual Java (JVM) host , y qué tan bien la JVM explota las características del hardware y del sistema operativo (SO) de la computadora al hacerlo. Por lo tanto, cualquier prueba o comparación de rendimiento de Java siempre debe informar la versión, el proveedor, el sistema operativo y la arquitectura de hardware de la JVM utilizada. De manera similar, el rendimiento del programa equivalente compilado de forma nativa dependerá de la calidad de su código de máquina generado, por lo que la prueba o comparación también debe informar el nombre, la versión y el proveedor del compilador utilizado, y sus directivas de optimización del compilador activadas. .
Métodos de optimización de máquinas virtuales
Muchas optimizaciones han mejorado el rendimiento de la JVM con el tiempo. Sin embargo, aunque Java fue a menudo la primera máquina virtual en implementarlos con éxito, también se han utilizado en otras plataformas similares.
Compilación justo a tiempo
Las primeras JVM siempre interpretaban los códigos de bytes de Java . Esto tuvo una gran penalización de rendimiento de entre un factor de 10 y 20 para Java frente a C en aplicaciones promedio. [5] Para combatir esto, se introdujo un compilador Just-In-Time (JIT) en Java 1.1. Debido al alto costo de compilación, se introdujo un sistema agregado llamado HotSpot en Java 1.2 y se convirtió en el predeterminado en Java 1.3. Con este marco, la máquina virtual Java analiza continuamente el rendimiento del programa en busca de puntos calientes que se ejecutan con frecuencia o repetidamente. Luego, estos se orientan a la optimización , lo que lleva a una ejecución de alto rendimiento con un mínimo de sobrecarga para un código menos crítico para el rendimiento. [6] [7] Algunos puntos de referencia muestran una ganancia de velocidad de 10 veces por este medio. [8] Sin embargo, debido a limitaciones 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 en informática que realiza una recopilación dinámica de partes de un programa en función del perfil de ejecución actual. Con una implementación simple, un optimizador adaptativo puede simplemente hacer un intercambio entre la compilación justo a tiempo y la interpretación de instrucciones. En otro nivel, la optimización adaptativa puede aprovechar las condiciones de los datos locales para optimizar las sucursales alejadas y utilizar la expansión en línea.
Una máquina virtual Java como HotSpot también puede desoptimizar el código anteriormente JITed. Esto permite realizar optimizaciones agresivas (y potencialmente inseguras), sin dejar de ser capaz de desoptimizar posteriormente el código y volver a una ruta segura. [11] [12]
Recolección de basura
Las máquinas virtuales Java (JVM) 1.0 y 1.1 usaban un recolector de barrido de marcas , que podía fragmentar el montón después de una recolección de basura. A partir de Java 1.2, las JVM cambiaron a un recopilador 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
Ups comprimidos
Los Ups comprimidos permiten que Java 5.0+ aborde hasta 32 GB de montón con referencias de 32 bits. Java no admite el acceso a bytes individuales, solo a los objetos que están alineados en 8 bytes de forma predeterminada. Debido a esto, los 3 bits más bajos de una referencia de montón siempre serán 0. Al reducir la resolución de las referencias de 32 bits a bloques de 8 bytes, el espacio direccionable se puede aumentar a 32 GB. Esto reduce significativamente el uso de memoria en comparación con el uso de referencias de 64 bits, ya que Java usa referencias mucho más que algunos lenguajes como C ++. Java 8 admite alineaciones más grandes, como la alineación de 16 bytes, para admitir hasta 64 GB con referencias de 32 bits. [ cita requerida ]
Verificación de código de bytes dividido
Antes de ejecutar una clase , Sun JVM verifica sus códigos de bytes de Java (consulte el verificador de códigos de bytes ). Esta verificación se realiza de forma perezosa: los códigos de bytes de las clases solo se cargan y verifican cuando la clase específica está cargada y preparada para su uso, y no al principio del programa. Sin embargo, dado que las bibliotecas de clases de Java también son clases regulares de Java, también deben cargarse cuando se utilizan, lo que significa que el tiempo de inicio de un programa Java suele ser más largo 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 la fuente hasta el código de bytes
- Tiempo de ejecución: al cargar una clase.
En la práctica, este método funciona capturando el conocimiento que tiene el compilador de Java sobre el flujo de clases y anotando los códigos de bytes del método compilado con una sinopsis de la información del flujo de clases. Esto no hace que la verificación en tiempo de ejecución sea apreciablemente menos compleja, pero permite algunos atajos. [ cita requerida ]
Análisis de escape y engrosamiento de cerraduras
Java es capaz de gestionar subprocesos múltiples a nivel de lenguaje. El subproceso múltiple es un método que permite a los programas realizar múltiples procesos al mismo tiempo, produciendo así programas más rápidos en sistemas informáticos con múltiples procesadores o núcleos. Además, una aplicación multiproceso puede seguir respondiendo a la entrada, incluso mientras realiza tareas de ejecución prolongada.
Sin embargo, los programas que utilizan subprocesos múltiples deben tener especial cuidado con los objetos compartidos entre subprocesos, bloqueando el acceso a métodos o bloques compartidos cuando son utilizados por uno de los subprocesos. Bloquear un bloque o un objeto es una operación que requiere mucho tiempo debido a la naturaleza de la operación de nivel del sistema operativo subyacente involucrada (ver control de concurrencia y granularidad de bloqueo ).
Como la biblioteca de Java no sabe qué métodos utilizará más de un subproceso, la biblioteca estándar siempre bloquea los bloques cuando es necesario en un entorno multiproceso.
Antes de Java 6, la máquina virtual siempre bloqueaba objetos y bloques cuando el programa se lo pedía, incluso si no había riesgo de que dos subprocesos diferentes modificaran un objeto a la vez. Por ejemplo, en este caso, vector
se bloqueó un local antes de cada una de las operaciones de adición para garantizar que no fuera modificado por otros subprocesos (el vector está sincronizado), pero debido a que es estrictamente local para el método, esto no es necesario:
public String getNames () { Vector < String > v = new Vector <> (); v . agregar ( "Yo" ); v . agregar ( "Usted" ); v . add ( "Ella" ); volver v . toString (); }
A partir de Java 6, los bloques de código y los objetos se bloquean solo cuando se necesitan, [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 análisis de escape. [17]
Registre las mejoras en la asignación
Antes de Java 6 , la asignación de registros era muy primitiva en la máquina virtual del cliente (no vivían en bloques ), lo que era un problema en los diseños de CPU que tenían menos registros de procesador disponibles, como en x86 . Si no hay más registros disponibles para una operación, el compilador debe copiar del registro a la memoria (o de la memoria al registro), lo que lleva tiempo (los registros son de acceso significativamente más rápido). Sin embargo, la máquina virtual del servidor utilizó un asignador de gráficos de colores y no tuvo este problema.
Se introdujo una optimización de la asignación de registros en el JDK 6 de Sun; [18] Entonces fue posible usar los mismos registros en todos los bloques (cuando corresponda), reduciendo los accesos a la memoria. Esto dio lugar a un aumento de rendimiento informado de alrededor del 60% en algunos puntos de referencia. [19]
Compartir datos de clase
El intercambio de datos de clases (llamado CDS por Sun) es un mecanismo que reduce el tiempo de inicio de las aplicaciones Java y también reduce la huella de memoria . Cuando se instala 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 vuelca esa representación en un archivo, llamado "archivo compartido". Durante las siguientes invocaciones de JVM, este archivo compartido se mapea en memoria , lo que ahorra el costo de cargar esas clases y permite que gran parte de los metadatos de JVM para estas clases se compartan entre múltiples procesos de JVM. [20]
La correspondiente mejora en el tiempo de puesta en marcha es más obvia para los programas pequeños. [21]
Historial de mejoras de rendimiento
Además de las mejoras enumeradas aquí, cada versión de Java introdujo muchas mejoras de rendimiento en la interfaz de programación de aplicaciones (API) JVM y Java .
JDK 1.1.6: Primera compilación justo a tiempo ( compilador JIT de Symantec ) [2] [22]
J2SE 1.2: Utilización de un recolector generacional .
J2SE 1.3: compilación Just-in-time por HotSpot .
J2SE 1.4: consulte aquí para obtener una descripción general de Sun de las mejoras de rendimiento entre las versiones 1.3 y 1.4.
Java SE 5.0: uso compartido de datos de clases [23]
Java SE 6:
- Verificación de código de bytes dividido
- Análisis de escape y engrosamiento de cerraduras
- Registre las mejoras en la asignación
Otras mejoras:
- Mejoras en la velocidad de la canalización Java OpenGL Java 2D [24]
- El rendimiento de Java 2D también mejoró significativamente en Java 6 [25]
Consulte también 'Descripción general de Sun sobre las mejoras de rendimiento entre Java 5 y Java 6'. [26]
Java SE 6 Update 10
- Java Quick Starter reduce el tiempo de inicio de la aplicación al precargar parte de los datos de JRE al inicio del sistema operativo en la memoria caché del disco . [27]
- Las partes de la plataforma necesarias para ejecutar una aplicación a la que se accede desde la web cuando JRE no está instalado ahora se descargan primero. El JRE completo es de 12 MB, una aplicación típica de Swing solo necesita descargar 4 MB para comenzar. Las partes restantes se descargan en segundo plano. [28]
- El rendimiento de los gráficos en Windows mejoró mediante el uso extensivo de Direct3D de forma predeterminada, [29] y el uso de sombreadores en la unidad de procesamiento de gráficos (GPU) para acelerar las operaciones complejas de Java 2D . [30]
Java 7
Se han lanzado varias mejoras de rendimiento para Java 7: Se planean mejoras de rendimiento futuras para una actualización de Java 6 o Java 7: [31]
- Proporcionar soporte JVM para lenguajes de programación dinámicos , siguiendo el trabajo de creación de prototipos que se realiza actualmente en la máquina Da Vinci (máquina virtual multilingüe), [32]
- Mejorar la biblioteca de simultaneidad existente administrando la computación paralela en procesadores de múltiples núcleos , [33] [34]
- Permita que la JVM utilice los compiladores JIT de cliente y servidor en la misma sesión con un método llamado compilación por niveles: [35]
- El cliente se usaría al inicio (porque es bueno al inicio y para aplicaciones pequeñas),
- El servidor se utilizaría para la ejecución a largo plazo de la aplicación (porque supera al compilador del cliente para esto).
- Reemplace el recolector de basura concurrente de pausa baja existente (también llamado recolector de barrido de marcas concurrentes (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 y uno equivalente escrito en otro lenguaje, como C ++, necesita un punto de referencia construido cuidadosa y cuidadosamente que compare programas que completan tareas idénticas. El objetivo de la plataforma de Java de código de bytes compilador es la plataforma Java , y el código de bytes está bien interpretado o compilado en código máquina por la JVM. Otros compiladores casi siempre apuntan a una plataforma específica de hardware y software, produciendo código de máquina que permanecerá prácticamente sin cambios durante la ejecución [ cita requerida ] . De estos dos enfoques diferentes surgen escenarios muy diferentes y difíciles de comparar: compilaciones y recompilaciones estáticas versus dinámicas , la disponibilidad de información precisa sobre el entorno de ejecución y otros.
Java a menudo se compila justo a tiempo en tiempo de ejecución por la máquina virtual Java , pero también se puede compilar con anticipación , al igual que C ++. Cuando se compilan justo a tiempo, los micro-benchmarks de The Computer Language Benchmarks Game indican lo siguiente acerca de su desempeño: [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 puntos de referencia a menudo miden el rendimiento de pequeños programas numéricamente intensivos. En algunos programas raros de la vida real, Java supera a C. Un ejemplo es el punto de referencia de Jake2 (un clon de Quake II escrito en Java mediante la traducción del código GPL C original ). La versión de Java 5.0 funciona mejor en algunas configuraciones de hardware que su contraparte de C. [42] Si bien no se especifica cómo se midieron los datos (por ejemplo, si se usó el ejecutable original de Quake II compilado en 1997, lo que puede considerarse malo ya que los compiladores de C actuales pueden lograr mejores optimizaciones para Quake), señala cómo lo mismo El código fuente de Java puede tener un gran aumento de velocidad con solo actualizar la máquina virtual, algo imposible de lograr con un enfoque 100% estático.
Para otros programas, la contraparte de C ++ puede, y generalmente lo hace, ejecutarse significativamente más rápido que el equivalente de Java. Un benchmark realizado por Google en 2011 mostró un factor 10 entre C ++ y Java. [43] En el otro extremo, una evaluación académica realizada en 2012 con un algoritmo de modelado 3D mostró que la JVM de Java 6 era de 1.09 a 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 determinadas circunstancias en C ++: [45]
- El uso de punteros de estilo C puede dificultar la optimización en idiomas que admiten punteros,
- El uso de métodos de análisis de escape está 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 punteros , [nota 1]
- Java puede acceder a métodos de instancia derivados más rápido de lo que C ++ puede acceder a métodos virtuales derivados debido a la búsqueda adicional de tablas virtuales de C ++. Sin embargo, los métodos no virtuales en C ++ no sufren cuellos de botella en el rendimiento de la tabla v y, por lo tanto, presentan un rendimiento similar al de Java.
La JVM también puede realizar optimizaciones específicas del procesador o expansión en línea . Y, la capacidad de desoptimizar el código ya compilado o en línea a veces le permite realizar optimizaciones más agresivas que las realizadas por lenguajes de tipado estático cuando están involucradas funciones de biblioteca externas. [46] [47]
Los resultados de los microbenchmarks entre Java y C ++ dependen en gran medida de las operaciones que se comparan. Por ejemplo, al comparar con Java 5.0:
- Las operaciones aritméticas de 32 y 64 bits, [48] [49] E / S de archivos [50] y Manejo de excepciones , [51] tienen un rendimiento similar a los programas C ++ comparables.
- El rendimiento de las operaciones de matrices [52] es mejor en C.
- El rendimiento de las funciones trigonométricas es mucho mejor en C. [53]
- Notas
- ^ La contención de esta naturaleza puede aliviarse en programas C ++ a nivel de código fuente empleando métodos avanzados como asignadores personalizados, explotando 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 anticipa) mientras el programa permanece en desarrollo primario.
Rendimiento multinúcleo
La escalabilidad y el rendimiento de las aplicaciones Java en sistemas de varios núcleos están limitados por la tasa de asignación de objetos. Este efecto a veces se denomina "muro 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 de basura, lo que hasta cierto punto alivia este problema. Se informa que algunos recolectores de basura mantienen tasas de asignación de más de 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 administración automática de memoria en Java permite el uso eficiente de estructuras de datos inmutables y sin cerrojo que son extremadamente difíciles o, a veces, imposibles de implementar sin algún tipo de recolección de basura. [ cita requerida ] Java ofrece una serie de estructuras de alto nivel en su biblioteca estándar en el paquete java.util.concurrent, mientras que muchos lenguajes históricamente utilizados para sistemas de alto rendimiento como C o C ++ todavía carecen de ellas. [ cita requerida ]
Tiempo de inicio
El tiempo de inicio de Java suele ser mucho más lento que muchos lenguajes, incluidos C , C ++ , Perl o Python , porque muchas clases (y en primer lugar las clases de las bibliotecas de clases de la plataforma ) deben cargarse antes de usarse.
En comparación con tiempos de ejecución populares similares, para programas pequeños que se ejecutan en una máquina con 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 vinculadas de entrada-salida (IO) en lugar de la inicialización de JVM o la carga de clases (el archivo de datos de clase rt.jar solo tiene 40 MB y la JVM debe buscar muchos datos en este archivo grande) . [27] Algunas pruebas mostraron que aunque el nuevo método de verificación de código de bytes dividido mejoró la carga de clases en aproximadamente un 40%, solo se dio cuenta de una mejora de inicio de aproximadamente un 5% para programas grandes. [58]
Aunque es una pequeña mejora, es más visible en programas pequeños que realizan una operación simple y luego salen, porque 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, Sun JRE viene con un Quick Starter que carga previamente los datos de clase al inicio del sistema operativo para obtener datos de la memoria caché del disco en lugar de hacerlo desde el disco.
Excelsior JET aborda el problema desde el otro lado. Su Startup Optimizer 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ó al público 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] presenta por primera vez una opción para que los scripts usen una JVM como demonio , para ejecutar una o más aplicaciones Java sin gastos generales de inicio de JVM. El demonio Nailgun no es seguro: "todos los programas se ejecutan con los mismos permisos que el servidor". Cuando se necesita seguridad multiusuario , Nailgun es inapropiado sin precauciones especiales. Scripts donde el inicio de JVM por aplicación domina el uso de recursos, vea mejoras de rendimiento en tiempo de ejecución de uno a dos órdenes de magnitud . [60]
Uso de memoria
El uso de memoria de Java es mucho mayor que el uso de memoria de C ++ porque:
- Hay una sobrecarga de 8 bytes para cada objeto y 12 bytes para cada matriz [61] en Java. Si el tamaño de un objeto no es un 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 4 u 8 bytes) para cada objeto cuya clase declara directa o indirectamente funciones virtuales . [62]
- La falta de aritmética de direcciones hace que la creación de contenedores eficientes en memoria, como estructuras estrechamente espaciadas y listas vinculadas XOR , sea actualmente imposible ( el proyecto OpenJDK Valhalla tiene como objetivo mitigar estos problemas, aunque no pretende introducir aritmética de punteros; esto no se puede hacer en un ambiente de recolección de basura).
- A diferencia de malloc y new, la sobrecarga de rendimiento promedio de la recolección de basura asintóticamente se acerca a cero (más exactamente, 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 conduce a una sobrecarga de memoria significativa para aplicaciones pequeñas. [ cita requerida ]
- Normalmente, las recompilaciones nativas y binarias de Java estarán en la memoria.
- La máquina virtual utiliza una gran cantidad de memoria.
- En Java, un objeto compuesto (clase A que usa instancias de B y C) se crea usando referencias a instancias asignadas de B y C. En C ++, el costo de 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 Java, la carga de clases y el cambio de tamaño automático de la memoria. Para los programas en los que la memoria es un factor crítico para elegir entre lenguajes y entornos de ejecución, se necesita 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 corresponder con la implementación de hardware subyacente. [65] En el subconjunto de coma flotante x87 , Java desde 1.4 realiza una reducción de argumentos para sin y cos en el software, [66] provocando un gran impacto en el rendimiento para valores fuera del rango. [67] [ aclaración necesaria ] JDK (11 y superior) tiene un progreso significativo en la velocidad de evaluación de las funciones trigonométricas en comparación con JDK 8. [68]
Interfaz nativa de Java
La interfaz nativa de Java invoca una gran sobrecarga, lo que hace que sea costoso cruzar el límite entre el código que se ejecuta en la JVM y el código nativo. [69] [70] Java Native Access (JNA) proporciona a los programas Java un fácil acceso a las bibliotecas compartidas nativas ( biblioteca de vínculos dinámicos (DLL) en Windows) únicamente a través del código Java, sin JNI ni código nativo. Esta funcionalidad es comparable a la plataforma / invocación de Windows y ctypes de Python . El acceso es dinámico en tiempo de ejecución sin generación de código. Pero tiene un costo y JNA suele ser más lento que JNI. [71]
Interfaz de usuario
Swing se ha percibido como más lento que los kits de herramientas de widgets nativos , porque delega la representación de widgets a la API pura de Java 2D . Sin embargo, los puntos de referencia que comparan el rendimiento de Swing con el Standard Widget Toolkit , que delega la representación a las bibliotecas GUI nativas del sistema operativo, no muestran un ganador claro y los resultados dependen en gran medida del contexto y los entornos. [72] Además, el marco JavaFX más nuevo , destinado a reemplazar a Swing, aborda muchos de los problemas inherentes de Swing.
Utilizar para informática 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 los puntos de referencia de computación intensiva, pero que las JVM todavía tienen problemas de escalabilidad para realizar una comunicación intensiva en una red de computación grid . [73]
Sin embargo, las aplicaciones informáticas de alto rendimiento escritas en Java han ganado concursos de referencia. 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ápido. Sin embargo, la configuración del hardware de los sistemas de la competencia no se corrigió. [77] [78]
En concursos de programación
Los programas en Java comienzan más lentamente que los de otros lenguajes compilados. [79] [80] Por lo tanto, algunos sistemas de jueces en línea, en particular 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.
Ver también
- Common Language Runtime
- Análisis de rendimiento
- Procesador Java , un procesador integrado que ejecuta código de bytes Java de forma nativa (como JStik )
- Comparación de Java y C ++
- Java ConcurrentMap
Referencias
- ^ http://www.scribblethink.org/Computer/javaCbenchmark.html
- ^ a b "El compilador Java Just-In-Time de Symantec se integrará en Sun JDK 1.1" .
- ^ "Toma corta: Apple otorga licencias al compilador justo a tiempo de Symantec" . cnet.com. 12 de mayo de 1998 . Consultado el 15 de noviembre de 2015 .
- ^ "Java se vuelve cuatro veces más rápido con el nuevo compilador Just-In-Time de Symantec" .
- ^ http://www.shudo.net/jit/perf/
- ^ Kawaguchi, Kohsuke (30 de marzo de 2008). "Profundización en el código ensamblador de Java" . Archivado desde el original el 2 de abril de 2008 . Consultado el 2 de abril de 2008 .
- ^ "Generación de código rápida y eficaz en un compilador de Java justo a tiempo" (PDF) . Intel Corporation . Consultado el 22 de junio de 2007 .
- ^ Este artículo muestra que la ganancia de rendimiento entre el modo interpretado y Hotspot asciende a más de un factor de 10.
- ^ Rendimiento numérico en C, C # y Java
- ^ Comparación de rendimiento algorítmico entre lenguajes de programación C, C ++, Java y C # Archivado el 31 de marzo de 2010 en Wayback Machine
- ^ "La máquina virtual Java HotSpot, v1.4.1" . Sun Microsystems . Consultado el 20 de abril de 2008 .
- ^ Nutter, Charles (28 de enero de 2008). "Lang.NET 2008: Pensamientos del día 1" . Consultado el 18 de enero de 2011 .
La desoptimización es muy emocionante cuando se trata de problemas de rendimiento, ya que significa que puede realizar optimizaciones mucho más agresivas ... sabiendo que podrá volver a un camino seguro probado más adelante
- ^ Biblioteca de IBM DeveloperWorks
- ^ Por ejemplo, ahora la duración de las pausas es menos notoria. Vea, por ejemplo, este clon de Quake II escrito en Java: Jake2 .
- ^ "Nueva característica de Java SE 6: Verificador de verificación de tipo" . Java.net . Consultado el 18 de enero de 2011 .[ enlace muerto permanente ]
- ^ 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 .
- ^ "Mejoras en el 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 Java Hotspot Server Compiler puede analizar el alcance de los usos de un nuevo objeto y decidir si asignarlo al montón de Java. El análisis de escape es compatible y habilitado de forma predeterminada en Java SE 6u23 y versiones posteriores.
- ^ Informe de error: nuevo asignador de registros, corregido en Mustang (JDK 6) b59
- ^ ¡ 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
- ^ Uso compartido de datos de clase en java.sun.com
- ^ Uso compartido de datos de clase en JDK 1.5.0 en Java Buzz Forum en artima developer
- ^ Mckay, Niali. "Java se vuelve cuatro veces más rápido con el nuevo compilador Just-In-Time de Symantec" .
- ^ Descripción general de Sun sobre las mejoras de rendimiento entre las versiones 1.4 y 5.0.
- ^ 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
- ^ Consulte aquí un punto de referencia que muestra un aumento de rendimiento de aproximadamente un 60% de Java 5.0 a 6 para la aplicación JFreeChart
- ^ Informe técnico de rendimiento de Java SE 6 en http://java.sun.com
- ^ a b Haase, Chet (mayo de 2007). "Consumidor JRE: tecnología Java más ágil, más mala" . Sun Microsystems . Consultado el 27 de julio de 2007 .
A nivel del sistema operativo, todos estos megabytes deben leerse desde el disco, lo cual es una operación muy lenta. En realidad, es el tiempo de búsqueda del disco lo que mata; leer archivos grandes de forma secuencial es relativamente rápido, pero buscar los bits que realmente necesitamos no lo es. Entonces, 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 en todos los archivos significa que hay mucha actividad en el disco.
- ^ Haase, Chet (mayo de 2007). "Consumidor JRE: tecnología Java más ágil, más mala" . Sun Microsystems . Consultado el 27 de julio de 2007 .
- ^ Haase, Chet (mayo de 2007). "Consumidor JRE: tecnología Java más ágil, más mala" . Sun Microsystems . Consultado el 27 de julio de 2007 .
- ^ Campbell, Chris (7 de abril de 2007). "Más rápido Java 2D a través de Shaders" . Archivado desde el original el 5 de junio de 2011 . Consultado el 18 de enero de 2011 .
- ^ Haase, Chet (mayo de 2007). "Consumidor JRE: tecnología Java más ágil, más mala" . Sun Microsystems . Consultado el 27 de julio de 2007 .
- ^ "JSR 292: soporte de lenguajes escritos dinámicamente en la plataforma Java" . jcp.org . Consultado el 28 de mayo de 2008 .
- ^ Goetz, Brian (4 de marzo de 2008). "Teoría y práctica de Java: clava un tenedor en él, parte 2" . Consultado el 9 de marzo de 2008 .
- ^ Lorimer, RJ (21 de marzo de 2008). "Paralelismo con Fork / Join en Java 7" . infoq.com . Consultado el 28 de mayo de 2008 .
- ^ "Nuevas optimizaciones del compilador en la máquina virtual Java HotSpot" (PDF) . Sun Microsystems. Mayo de 2006 . Consultado el 30 de mayo de 2008 .
- ^ Humble, Charles (13 de mayo de 2008). "JavaOne: basura primero" . infoq.com . Consultado el 7 de septiembre de 2008 .
- ^ Coward, Danny (12 de noviembre de 2008). "Java VM: probando un nuevo recolector de basura para JDK 7" . Archivado desde el original el 8 de diciembre de 2011 . Consultado el 15 de noviembre de 2008 .
- ^ "Juego de Benchmarks de Lenguaje de Computadora" . benchmarksgame.alioth.debian.org. Archivado desde el original el 25 de enero de 2015 . Consultado el 2 de junio de 2011 .
- ^ "Juego de Benchmarks de Lenguaje de Computadora" . benchmarksgame.alioth.debian.org. Archivado desde el original el 13 de enero de 2015 . Consultado el 2 de junio de 2011 .
- ^ "Juego de Benchmarks de Lenguaje de Computadora" . benchmarksgame.alioth.debian.org. Archivado desde el original el 10 de enero de 2015 . Consultado el 2 de junio de 2011 .
- ^ "Juego de Benchmarks de Lenguaje de Computadora" . benchmarksgame.alioth.debian.org. Archivado desde el original el 2 de enero de 2015 . Consultado el 2 de junio de 2011 .
- ^ : 260/250 fotogramas / s frente a 245 fotogramas / s (consulte el punto de referencia )
- ^ Hundt, Robert. "Reconocimiento de bucles en C ++ / Java / Go / Scala" (PDF) . Días Scala 2011 . Stanford, California . Consultado el 23 de marzo de 2014 .
- ^ L. Gherardi; D. Brugali; D. Comotti (2012). "Una evaluación de rendimiento de Java vs. C ++: un punto de referencia de modelado 3D" (PDF) . Universidad de Bérgamo . Consultado el 23 de marzo de 2014 .
El uso del compilador del servidor, que está mejor ajustado para aplicaciones de larga ejecución, ha demostrado en cambio que Java es de 1.09 a 1.91 veces más lento (...) En conclusión, los resultados obtenidos con el compilador del servidor y estas características importantes sugieren que Java puede ser considerado una alternativa válida a C ++
- ^ Lewis, JP; Neumann, Ulrich. "Rendimiento de Java versus C ++" . Laboratorio de gráficos por computadora y tecnología inmersiva, Universidad del Sur de California.
- ^ "El motor de rendimiento de Java HotSpot: ejemplo de inserción de métodos" . Oracle Corporation . Consultado el 11 de junio de 2011 .
- ^ Nutter, Charles (3 de mayo de 2008). "El poder de la JVM" . Consultado el 11 de junio de 2011 .
¿Qué sucede si ya ha incluido el método de A cuando aparece B? Aquí vuelve a brillar la JVM. Debido a que la JVM es esencialmente un tiempo de ejecución de lenguaje dinámico bajo las sábanas, permanece siempre alerta, observando exactamente que sucedan este tipo de eventos. Y aquí está la parte realmente interesante: cuando las situaciones cambian, la JVM puede desoptimizar. Este es un detalle crucial. Muchos otros tiempos de ejecución solo pueden realizar su optimización una vez. Los compiladores de C deben hacerlo todo antes de tiempo, durante la compilación. Algunos le permiten crear un perfil de su aplicación y alimentarlo en las compilaciones posteriores, pero una vez que haya publicado un fragmento de código, es esencialmente lo más optimizado que nunca. Otros sistemas similares a máquinas virtuales, como CLR, tienen una fase JIT, pero ocurre al principio de la ejecución (tal vez antes de que el sistema comience a ejecutarse) y nunca vuelve a suceder. La capacidad de la JVM para desoptimizar y volver a la interpretación le da espacio para ser optimista ... espacio para hacer conjeturas ambiciosas y volver con gracia a un estado seguro, para volver a intentarlo más tarde.
- ^ "Microbenchmarking C ++, C # y Java: aritmética de enteros de 32 bits" . Diario del Dr. Dobb . 1 de julio de 2005 . Consultado el 18 de enero de 2011 .
- ^ "Microbenchmarking C ++, C # y Java: aritmética doble de 64 bits" . Diario del Dr. Dobb . 1 de julio de 2005 . Consultado el 18 de enero de 2011 .
- ^ "Microbenchmarking C ++, C # y Java: E / S de archivos" . Diario del Dr. Dobb . 1 de julio de 2005 . Consultado el 18 de enero de 2011 .
- ^ "Microbenchmarking C ++, C # y Java: excepción" . Diario del Dr. Dobb . 1 de julio de 2005 . Consultado el 18 de enero de 2011 .
- ^ "Microbenchmarking C ++, C # y Java: Array" . Diario del Dr. Dobb . 1 de julio de 2005 . Consultado el 18 de enero de 2011 .
- ^ "Microbenchmarking C ++, C # y Java: funciones trigonométricas" . Diario del Dr. Dobb . 1 de julio de 2005 . Consultado el 18 de enero de 2011 .
- ^ 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 24a conferencia ACM SIGPLAN sobre lenguajes y aplicaciones de sistemas de programación orientados a objetos , 2009.
- ^ C4: El colector de compactación continuamente concurrente
- ^ Azul intimida a Java con una máquina de 768 núcleos
- ^ "Benchmark de puesta en marcha y rendimiento del sistema para .Net, Mono, Java, C ++ y su respectiva UI" . 2 de septiembre de 2010.
- ^ "¿Qué tan rápido es el nuevo verificador?" . 7 de febrero de 2006. Archivado desde el original el 16 de mayo de 2006 . Consultado el 9 de mayo de 2007 .
- ^ Pistola de clavos
- ^ Lapágina de antecedentes de la pistola de clavosmuestra unaaceleración de 33 veces en el" mejor escenario de caso " (para programas con guión "¡Hola, mundo!", Es decir, programas de ejecución corta).
- ^ http://www.javamex.com/tutorials/memory/object_memory_usage.shtml
- ^ "Copia archivada" . Archivado desde el original el 21 de febrero de 2008 . Consultado el 22 de junio de 2009 .CS1 maint: copia archivada como título ( enlace )
- ^ https://www.youtube.com/watch?v=M91w0SBZ-wc : Comprensión de la recolección de basura de Java: una charla de Gil Tene en JavaOne
- ^ http://www.tommti-systems.de/go.html?http://www.tommti-systems.de/main-Dateien/reviews/languages/benchmarks.html
- ^ "Matemáticas (Java Platform SE 6)" . Sun Microsystems . Consultado el 8 de junio de 2008 .
- ^ Gosling, James (27 de julio de 2005). "Meditación trascendental" . Archivado desde el original el 12 de agosto de 2011 . Consultado el 8 de junio de 2008 .
- ^ W. Cowell-Shah, Christopher (8 de enero de 2004). "Resumen de rendimiento de nueve idiomas: evaluación comparativa de matemáticas y E / S de archivos" . Archivado desde el original el 11 de octubre de 2018 . Consultado el 8 de junio de 2008 .
- ^ SV Chekanov, G. Gavalian, NA Graf, Jas4pp - un marco de análisis de datos para estudios de detección y física, (2020), ( https://arxiv.org/abs/2011.05329 ) (2020) ANL-HEP-164101, SLAC-PUB-17569
- ^ Wilson, Steve; Jeff Kesselman (2001). "Rendimiento de la plataforma JavaTM: uso de código nativo" . Sun Microsystems . Consultado el 15 de febrero de 2008 .
- ^ Kurzyniec, Dawid; Vaidy Sunderam. "Cooperación eficiente entre Java y códigos nativos - JNI Performance Benchmark" (PDF) . Archivado desde el original (PDF) el 14 de febrero de 2005 . Consultado el 15 de febrero de 2008 .
- ^ "¿Cómo se compara el rendimiento de JNA con el JNI personalizado?" . Sun Microsystems . Consultado el 26 de diciembre de 2009 .[ enlace muerto permanente ]
- ^ Igor, Križnar (10 de mayo de 2005). "Comparación de rendimiento SWT Vs. Swing" (PDF) . cosylab.com. Archivado desde el original (PDF) el 4 de julio de 2008 . Consultado el 24 de mayo de 2008 .
Es difícil dar una regla empírica en la que SWT supere al swing, o viceversa. En algunos entornos (por ejemplo, Windows), SWT es un ganador. En otros (Linux, VMware con Windows), Swing y su optimización de redibujado superan significativamente a SWT. Las diferencias en el desempeño son significativas: los factores de 2 y más son comunes, en cualquier dirección
- ^ Brian Amedro; Vladimir Bodnartchouk; Denis Caromel; Christian Delbe; Fabrice Huet; Guillermo L. Taboada (agosto de 2008). "Estado actual de Java para HPC" . INRIA . Consultado el 9 de septiembre de 2008 .
Primero realizamos algunos micro benchmarks para varias JVM, mostrando el buen desempeño general para operaciones aritméticas básicas (...). Al comparar esta implementación con una de Fortran / MPI, mostramos que tienen un rendimiento similar en evaluaciones comparativas intensivas en computación, pero aún tienen problemas de escalabilidad al realizar comunicaciones intensivas.
- ^ Owen O'Malley - Yahoo! Equipo de Computación Grid (julio de 2008). "Apache Hadoop gana la prueba comparativa de clasificación de terabytes" . Archivado desde el original el 15 de octubre de 2009 . Consultado el 21 de diciembre de 2008 .
Esta es la primera vez que gana un programa Java o de código abierto.
- ^ "Hadoop ordena un petabyte en 16.25 horas y un terabyte en 62 segundos" . CNET.com . 11 de mayo de 2009. Archivado desde el original el 16 de mayo de 2009 . Consultado 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)
- ^ "Hadoop rompe récords mundiales de clasificación de datos" . CNET.com . 15 de mayo de 2009 . Consultado el 8 de septiembre de 2010 .
- ^ Chris Nyberg; Mehul Shah. "Ordenar la página de inicio de Benchmark" . Consultado el 30 de noviembre de 2010 .
- ^ Czajkowski, Grzegorz (21 de noviembre de 2008). "Ordenando 1PB con MapReduce" . Consultado el 1 de diciembre de 2010 .
- ^ "Copia archivada" . Archivado desde el original el 18 de octubre de 2010 . Consultado el 21 de junio de 2010 .CS1 maint: copia archivada como título ( enlace )
- ^ http://acm.timus.ru/help.aspx?topic=java&locale=en
- ^ http://acm.pku.edu.cn/JudgeOnline/faq.htm#q11
- ^ "Copia archivada" . Archivado desde el original el 29 de junio de 2010 . Consultado el 25 de mayo de 2010 .CS1 maint: copia archivada como título ( enlace )
- ^ http://www.codechef.com/wiki/faq#How_does_the_time_limit_work
- ^ "Copia archivada" . Archivado desde el original el 19 de febrero de 2012 . Consultado el 13 de noviembre de 2011 .CS1 maint: copia archivada como título ( enlace )
- ^ http://poj.org/faq.htm#q9
enlaces externos
- Sitio dedicado a la información sobre el rendimiento de Java
- Depurar problemas de rendimiento de Java
- Portal de rendimiento de Java de Sun
- El mapa mental basado en presentaciones de ingenieros en la rama de SPb Oracle (como imagen PNG grande)