java - informacion - php5
Java Runtime Performance Vs Native C/C++ Code? (10)
Cada vez me siento más cómodo programando en Java que con C ++ o C. Espero tener una idea del impacto en el rendimiento incurrido usando un intérprete JVM, en lugar de ejecutar el mismo "proyecto" de forma nativa. Me doy cuenta de que hay un cierto nivel de subjetividad aquí; la calidad del programa dependerá en gran medida de una buena implementación. Me interesan los siguientes aspectos en un sentido general:
Debe haber algo de referencia para gastos generales cuando se usa un intérprete. ¿Hay alguna regla general para recordar? 10% 15%? (Saqué estos números de la nada) He leído ocasionalmente un blog que dice que el código Java es casi tan rápido como el código nativo, pero creo que puede haber sido parcial.
¿El recolector de elementos no utilizados de JVM agrega una sobrecarga significativa al rendimiento del tiempo de ejecución? Sé que las aplicaciones de Cocoa han comenzado a usar un modelo de recolección de basura, y estoy de acuerdo en que hace que la programación sea mucho más simple, pero ¿a qué costo?
¿Cuál es la sobrecarga de realizar llamadas al sistema desde Java? Por ejemplo, crear un objeto Socket en lugar de la API de socket C.
Finalmente, recuerdo haber leído en alguna parte que la implementación de JVM tiene un único hilo. Si esto es cierto (sobre lo que soy escéptico), ¿eso significa que los hilos de Java realmente no son hilos verdaderos? ¿Un hilo de Java, en general, corresponde a un subproceso proporcionado por núcleo subyacente? ¿Una aplicación Java se beneficia de la misma manera que una aplicación nativa de múltiples núcleos / múltiples CPU?
Cualquier consejo del desarrollador que entienda las complejidades de JVM y el rendimiento del programa Java sería muy apreciado. Gracias.
Como su objetivo es muy modesto, "espero tener una idea del rendimiento alcanzado ...", usted debería ser capaz de cumplir con la mayoría al examinar los programas y las medidas que se muestran en el Juego de parámetros de lenguaje de la computadora .
Como sabes, tanto Java como C ++
puede ver el código fuente del programa y decidir por usted cuál de los programas Java es razonable comparar con cuál de los programas C y C ++
puede ver las doce tareas diferentes y decidir por su cuenta cuál de ellas ejerce su idea de "las características más básicas de cada idioma"
puede ver los diferentes enfoques de multinúcleo o los programas forzados en un núcleo
puede verificar cuánto arranque de JVM podría o no afectar esas mediciones
Pero debe pensar si las medidas de los programas pequeños pueden indicar de manera plausible el rendimiento probable de su aplicación .
Consulte here , para una comparación detallada.
En realidad, una VM puede hacer muchas optimizaciones en tiempo de ejecución, basadas en información que solo está disponible en tiempo de ejecución, que un compilador de C / C ++ no puede hacer. Entonces, en la mayoría de las circunstancias, la JVM será al menos tan rápida como un programa nativo.
Brian Goetz responde la mayoría de sus preguntas, si no todas, en su conferencia Hacia una VM universal .
Java no es un lenguaje interpretado, y no ha sido para varias versiones. El bytecode de Java está JIT ''sobre la marcha. (Técnicamente aún interpreta parte del código, pero todo lo que importa en cuanto a rendimiento obtiene JIT)
En cuanto al rendimiento, ¿qué demonios te da la loca idea de que "hay una línea base para la sobrecarga"? No hay Nunca hubo y nunca habrá. No entre C ++ y Java, y no entre Python y Javascript, o cualquier otro idioma. Hay cosas que su versión específica de la JVM hará más rápido que su compilador C ++ específico, y cosas que su compilador C ++ específico hará mejor que su JVM específica.
De modo que la "sobrecarga" de su elección de idioma depende enteramente de 1) qué quiere que haga su código, y 2) cómo escribe su código.
Si toma un programa Java y lo traduce a C ++, el resultado casi seguro será más lento.
Si tomas un programa C ++ y lo traduces a Java, también se ejecutará más lento.
No porque un idioma sea "más rápido" que el otro, sino porque el programa original fue escrito para un idioma y fue diseñado para funcionar bien en ese idioma. Y cualquier intento de traducirlo a otro idioma perderá esta ventaja. Usted termina con un programa Java de estilo C ++, que no se ejecutará de manera eficiente en la JVM, o un programa C ++ estilo Java, que también se ejecutará terriblemente .
Ninguna especificación de idioma contiene una cláusula que "y el resultado debe ser al menos un x% más lento que el lenguaje y". Tanto el compilador de C ++ como la JVM hacen todo lo posible para que todo funcione rápido.
Y a continuación, las características de rendimiento que está viendo hoy pueden cambiar mañana. Los idiomas no tienen velocidad.
Pero para responder a sus preguntas específicas:
Debe haber algo de referencia para gastos generales cuando se usa un intérprete. ¿Hay alguna regla general para recordar? 10% 15%? He leído el blog ocasional que indica que el código Java es casi tan rápido como el código nativo, pero que puede haber sido parcial.
Como se dijo anteriormente, depende. Para muchas tareas comunes, normalmente no verá más que unos pocos porcentajes de diferencia en ambos sentidos. Para algunos casos de uso, verá una mayor diferencia (yendo de cualquier manera. Ambos lenguajes tienen ventajas en lo que respecta al rendimiento. Hay algunos gastos generales asociados con la JVM, pero también hay grandes oportunidades de optimización y no menos importante el recolector de basura)
¿El recolector de elementos no utilizados de JVM agrega una sobrecarga significativa al rendimiento del tiempo de ejecución? Sé que las aplicaciones de Cocoa han comenzado a usar un modelo de recolección de basura, y estoy de acuerdo en que hace que la programación sea mucho más simple, pero ¿a qué costo?
Básicamente ninguno. En promedio, un recolector de basura es mucho más rápido que la gestión de memoria manual, por muchas razones:
- en un montón administrado, las asignaciones dinámicas se pueden hacer mucho más rápido
- la propiedad compartida se puede manejar con un costo amortizado insignificante, donde en un idioma nativo tendría que usar el recuento de referencias que es terriblemente caro
- en algunos casos, la destrucción de objetos también se simplifica enormemente (la mayoría de los objetos de Java pueden recuperarse con sólo pasar GC el bloque de memoria. En C ++ los destructores siempre deben ejecutarse, y casi todos los objetos tienen uno)
El principal problema con un GC es que, aunque en promedio un recolector de basura funciona mejor, se pierde cierto control sobre cuándo tomar el costo de rendimiento. La administración manual de la memoria garantiza que su hilo nunca se detenga mientras espera que se limpie la memoria. Un recolector de basura puede, en casi cualquier momento, decidir pausar el proceso y limpiar la memoria. En casi todos los casos, esto es lo suficientemente rápido como para no ser un problema, pero para cosas vitales en tiempo real, es un problema.
(Un problema adicional es que pierde un poco de expresividad. En C ++, RAII se usa para administrar todo tipo de recursos. En Java, no puede usar RAII. En cambio, el GC maneja la memoria para usted y para todos los demás recursos, estás jodido, y tienes que hacerlo tú mismo con muchos bloques try / finally. No hay ninguna razón por la que RAII no pueda implementarse en un lenguaje GC, pero no está disponible ni en Java ni en C #)
¿Cuál es la sobrecarga de realizar llamadas al sistema desde Java? Por ejemplo, crear un objeto Socket en lugar de la API de socket C.
Aproximadamente lo mismo. ¿Por qué sería diferente? Por supuesto, Java tiene que invocar los API y servicios del sistema operativo relevantes, por lo que hay un poco de sobrecarga, pero en realidad no es nada probable.
Finalmente, recuerdo haber leído en alguna parte que la implementación de JVM tiene un único hilo. Si esto es cierto (sobre lo que soy escéptico), ¿eso significa que los hilos de Java realmente no son hilos verdaderos? ¿Un hilo de Java, en general, corresponde a un subproceso proporcionado por núcleo subyacente? ¿Una aplicación Java se beneficia de la misma manera que una aplicación nativa de múltiples núcleos / múltiples CPU?
Java puede usar múltiples hilos, sí. La propia JVM podría ser singlethreaded (en el sentido de que todos los servicios de JVM se ejecutan en el mismo hilo), no sé de eso. Pero su aplicación Java puede usar tantos subprocesos como quiera, y se asignan a subprocesos del sistema operativo y usarán varios núcleos.
Lo importante para anotar es
Código de bytes Java JIT compilado para un código mucho más optimizado específico para un hardware particular
vs
Código C compilado y optimizado para hardware general, por lo que no puede aprovechar las funciones proporcionadas por hardware específico
Mucha gente subestima el rendimiento de Java. Una vez tuve curiosidad por esto y escribí un programa simple en Java y luego un equivalente en c (no mucho más que hacer algunas operaciones con un bucle for y una matriz masiva). No recuerdo las cifras exactas, pero sí sé que java venció c cuando el programa c no se compiló con ningún indicador de optimización (en gcc). Como era de esperar, c se adelantó cuando finalmente lo compilé con una optimización agresiva. Para ser honesto, no fue un experimento científico de ninguna manera, pero me dio una referencia para saber dónde estaba Java.
Por supuesto, java probablemente se queda atrás cuando comienzas a hacer cosas que requieren llamadas al sistema. Sin embargo, he visto un rendimiento de lectura de 100MB / s con discos y redes con programas Java que se ejecutan en un hardware modesto. No estoy seguro de lo que dice exactamente, pero me indica que es lo suficientemente bueno para prácticamente cualquier cosa que necesite.
En cuanto a los hilos, si tu programa java crea 2 hilos, entonces tienes 2 hilos reales .
No hay una respuesta fácil para esto. Escribir el estilo C C ++ es posible (incluso una buena idea), pero una vez que intentas heredar en C, las cosas se ponen feas. Así que ignora C e ir con Java -vs-C ++ ya que están más cerca el uno del otro.
Para tener una idea real de esto, necesitarás escribir dos aplicaciones relativamente grandes de manera similar en ambos idiomas. Si haces eso, ¿utilizas las clases de colección STL y Java o escribes las tuyas propias y las transfieres entre idiomas? Si usa el nativo, depende de qué implementación sea más rápida, ya que si usa la suya no está probando la velocidad real de la aplicación.
Diría que tendrías que escribir la aplicación lo más similar posible pero usar las bibliotecas / expresiones idiomáticas específicas del idioma donde tenga sentido. Los códigos C ++ y Java, aunque son similares, tienen diferentes formas de hacer las cosas; algo que es fácil en Java puede ser terriblemente difícil en C ++ y viceversa.
Una implementación GC moderna no agrega tanta sobrecarga, y puede cambiar a un GC en C ++ para hacer la comparación si lo desea :-)
Hay algunas cosas que el tiempo de ejecución de Java puede hacer y que generalmente no se realizan en compiladores de C ++, como la capacidad de incorporar métodos virtuales.
Para cosas del tipo de sistema, Java normalmente recurre a realizar llamadas en C, por lo que hay gastos generales allí (aunque JNI es más rápido de lo que solía ser).
Enhebrar depende de la implementación. Sun solía usar "hilos verdes" para Solaris, pero eso ya pasó hace mucho tiempo. Hasta donde yo sé, la mayoría de las máquinas virtuales modernas usan hilos nativos.
En resumen, no creo que haya una buena métrica en el% de gastos generales para Java -vs-C ++, y cualquiera que encuentre probablemente sea un micro benchmark que no represente el mundo real (desafortunadamente).
Para abordar cada uno de sus puntos:
- La sobrecarga del código de interpretación es mucho más alta que 10-15% (supongo que a lo largo de 3x-5x o superior). Para bajar al 10-15%, debe usar algún tipo de paso de compilación de código de máquina (es decir, JIT). (Intenta ejecutar una JVM con JIT desactivado, y verás que el rendimiento cae como una roca).
- La recolección de basura tiene un impacto en el rendimiento, pero yo diría que todos están de acuerdo en que vale la pena. Si puede pagar la sobrecarga de compilación / interpretación de código de bytes, también puede pagar la sobrecarga de gc.
- La programación de socket es mucho más fácil en Java que en C / C ++, si eso es lo que estás preguntando. Y en cuanto a rendimiento, la sobrecarga de E / S de socket domina sobre la sobrecarga de ejecución de Java.
- La mayoría de las JVM modernas tienen subprocesos verdaderos, es decir, cada subproceso de Java se ejecuta mediante un subproceso de kernel, lo que permite que los subprocesos de Java utilicen CPUs multinúcleo modernas.
Tanto java como c # (y objetivo-c) no son tan rápidos como el código nativo. Pero eso solo importa si tienes un problema en el que no tienes tiempo de ingeniería. Porque tendrás tiempo para idear un mejor algoritmo con un lenguaje de alto nivel.
Entonces, básicamente, si está desarrollando un dispositivo en el que va a construir un millón al año, o que funciona con baterías, no usa java o c # para construir su funcionalidad principal. Sin embargo, puede agregar un intérprete de lisp para facilitar la personalización. Microsoft no va a usar c # para decir el núcleo del servidor SQL, donde el rendimiento realmente importa. Por otro lado, Visual Studio, donde MS puede esperar que los usuarios tengan hardware de alta gama, se puede usar como un escaparate para una tecnología lenta pero de alta productividad.
Tenga en cuenta que actualmente hago la mayor parte de mi programación en Pharo Smalltalk, que es mucho más lenta que java, c # u objetivo-c, y ni siquiera es uno de los Smalltalks más rápidos. La productividad supera el rendimiento.
http://www.w3sys.com/pages.meta/benchmarks.html
http://www.freewebs.com/godaves/javabench_revisited/
http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B#Performance
http://blog.dhananjaynene.com/2008/07/performance-comparison-c-java-python-ruby-jython-jruby-groovy/
http://www.irrlicht3d.org/pivot/entry.php?id=446
Y así. El hecho es que no importa . Los cuellos de botella y el software lento son creados por los desarrolladores, no por el lenguaje (al menos hoy en día).