a. ¿Cómo se compara hoy la velocidad de Java con C ++?
Difícil de medir. Vale la pena señalar que una parte importante de la velocidad de una implementación, su asignador de memoria, son algoritmos muy diferentes en Java y C ++. La naturaleza no determinista del recopilador hace que sea extremadamente difícil obtener datos de rendimiento significativos en comparación con la gestión de memoria determinista de C ++, porque nunca puede estar seguro de en qué estado se encuentra el recopilador. Esto significa que es muy difícil escribir un punto de referencia eso podría compararlos significativamente. Algunos patrones de asignación de memoria se ejecutan mucho más rápido con un GC, algunos se ejecutan mucho más rápido con un asignador nativo.
Lo que diría, sin embargo, es que el GC de Java debe ejecutarse rápidamente en cada situación. Sin embargo, un asignador nativo puede cambiarse por uno más apropiado. Recientemente envié una pregunta en SO sobre por qué un C # Dictionary
podría ejecutarse (0.45 ms en mi máquina) en comparación con un equivalentestd::unordered_map
que se ejecutó el (10 ms en mi máquina). Sin embargo, simplemente cambiando el asignador y el hasher por otros más apropiados, reduje el tiempo de ejecución a 0,34 ms en mi máquina, una trigésima parte del tiempo de ejecución original. Nunca, nunca podría esperar realizar ese tipo de optimización personalizada con Java. Un excelente ejemplo de dónde esto puede hacer una verdadera diferencia es el enhebrado. Las bibliotecas de subprocesos nativas como TBB proporcionan asignadores de almacenamiento en caché de subprocesos que son masivamente más rápidos que los asignadores tradicionales cuando se trata de muchas asignaciones en muchos subprocesos.
Ahora, muchas personas hablarán sobre las mejoras de JIT y cómo el JIT tiene más información. Claro, eso es verdad. Pero aún no está ni remotamente cerca de lo que puede obtener un compilador de C ++, porque el compilador tiene, comparativamente, tiempo y espacio infinitos en los que ejecutar, desde la perspectiva del tiempo de ejecución del programa final. Cada ciclo y cada byte que el JIT pasa pensando en cómo optimizar mejor su programa es un ciclo que su programa no está gastando en ejecutar y no puede usar para sus propias necesidades de memoria.
Además, siempre habrá momentos en que las optimizaciones del compilador y JIT no puedan probar ciertas optimizaciones, especialmente en el caso de cosas como el análisis de escape. En C ++, como el valor está en la pila de todos modos , el compilador no necesita realizarlo. Además, hay cosas simples, como la memoria contigua. Si asigna una matriz en C ++, entonces asigna una matriz única y contigua. Si asigna una matriz en Java, entonces no es contigua en absoluto, porque la matriz solo está llena de punteros que podrían apuntar a cualquier parte. Esto no es solo una sobrecarga de memoria y tiempo para las indirecciones dobles, sino también gastos generales de caché. Este tipo de cosas es donde la semántica del lenguaje de Java simplemente impone que debe ser más lento que el código C ++ equivalente.
En última instancia, mi experiencia personal es que Java podría ser aproximadamente la mitad de la velocidad de C ++, en promedio. Sin embargo, no existe una forma realista de hacer una copia de seguridad de las declaraciones de rendimiento sin un conjunto de puntos de referencia extremadamente completo, debido a los algoritmos fundamentalmente diferentes involucrados.
si. ¿Sería posible crear un título AAA moderno usando Java?
Supongo que te refieres a "juego", aquí, y no a una oportunidad. En primer lugar, tendría que escribir todo desde cero, ya que casi todas las bibliotecas existentes y la infraestructura se dirigen a C ++. Si bien no lo hace imposible per se, ciertamente podría contribuir de manera sólida hacia lo inviable. En segundo lugar, incluso los motores C ++ difícilmente pueden adaptarse a las pequeñas limitaciones de memoria de las consolas existentes, si las JVM existen para esas consolas, y los jugadores de PC esperan un poco más por su memoria. Crear juegos AAA con rendimiento es bastante difícil en C ++, no veo cómo se podría lograr en Java. Nadie ha escrito un juego AAA con un tiempo significativo en un lenguaje no compilado. Más que eso, simplemente sería extremadamente propenso a errores. La destrucción determinista es esencial cuando se trata, por ejemplo, con recursos de GPU, y en Java, usted '
C. ¿En qué áreas específicamente Java es más lento que C ++, si es que lo hace? (es decir, números, gráficos o simplemente todo)
Definitivamente iría por todos lados. La naturaleza de referencia forzada de todos los objetos Java significa que Java tiene muchas más indirectas y referencias que C ++, un ejemplo que di anteriormente con matrices, pero que también se aplica a todos los objetos miembros, por ejemplo. Cuando un compilador de C ++ puede buscar una variable miembro en tiempo constante, un tiempo de ejecución de Java debe seguir otro puntero. Cuantos más accesos haga, más lento será esto, y el JIT no puede hacer nada al respecto.
Donde C ++ puede liberar y reutilizar un trozo de memoria casi al instante, en Java hay que esperar a la colección, y espero que ese trozo no se quede sin caché, e inherentemente requerir más memoria significa menos caché y rendimiento de paginación. Luego mire la semántica para cosas como boxeo y unboxing. En Java, si desea hacer referencia a un int, debe asignarlo dinámicamente. Esa es una pérdida inherente en comparación con la semántica de C ++.
Entonces tienes el problema de los genéricos. En Java, solo puede operar en objetos genéricos a través de la herencia en tiempo de ejecución. En C ++, las plantillas tienen literalmente cero sobrecarga, algo que Java no puede igualar. Esto significa que todo el código genérico en Java es inherentemente más lento que un equivalente genérico en C ++.
Y luego llegas a Comportamiento indefinido. Todos odian cuando su programa exhibe UB, y todos desean que no existiera. Sin embargo, UB fundamentalmente permite optimizaciones que nunca pueden existir en Java. Echa un vistazo a esta publicación que describe las optimizaciones basadas en UB. No definir el comportamiento significa que las implementaciones pueden hacer más optimizaciones y reducir el código requerido para verificar las condiciones que estarían indefinidas en C ++ pero definidas en Java.
Fundamentalmente, la semántica de Java dicta que es un lenguaje más lento que C ++.
¿Se considera Java ahora un lenguaje compilado o un lenguaje interpretado?
Realmente no encaja en ninguno de esos grupos. Diría que gestionado es realmente una categoría separada por sí mismo, aunque diría que definitivamente se parece más a un lenguaje interpretado que a un lenguaje compilado. Más importante aún, solo hay dos sistemas gestionados principales, el JVM y el CLR, y cuando dice "gestionado" es suficientemente explícito.
¿Cuáles son algunas de las principales deficiencias de Java que se han abordado desde los primeros días?
Boxeo automático y unboxing es lo único que sé. Los genéricos resuelven algunos problemas, pero lejos de muchos.
¿Cuáles son algunas de las principales deficiencias de Java que aún no se han abordado?
Sus genéricos son muy, muy débiles. Los genéricos de C # son considerablemente más fuertes, aunque, por supuesto, tampoco lo son las plantillas. La destrucción determinista es otra falta importante. Cualquier forma de lambda / cierre también es un problema importante: puede olvidar una API funcional en Java. Y, por supuesto, siempre existe el problema del rendimiento, para aquellas áreas que los necesitan.