new icon example borderfactory java performance erlang compare

example - my icon java



¿Por qué Erlang es más lento que Java en todos estos pequeños puntos de referencia matemáticos? (7)

Como se señaló en otras respuestas, Erlang está diseñado para resolver efectivamente problemas de la vida real, que son un poco opuestos a los problemas de referencia.

Pero me gustaría aclarar un aspecto más: la esencia del código erlang (en algunos casos significa rapidez de desarrollo), que podría concluirse fácilmente, después de comparar implementaciones de puntos de referencia.

Por ejemplo, k-nucleótido de referencia:
Versión de Erlang: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=hipe&id=3
Versión de Java: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=java&id=3

Si desea más puntos de referencia de la vida real, le sugiero que compare C ++ y Erlang para el software de telecomunicaciones de Motorola.

Al considerar las alternativas para Java para un entorno distribuido / concurrente / de conmutación por error / escalable, descubrí Erlang. He dedicado algo de tiempo a libros y artículos en los que casi todos ellos (incluso los adictos a Java) dicen que Erlang es una mejor opción en este tipo de entornos, ya que muchas cosas útiles están listas para usar en una forma menos propensa a errores.

Estaba seguro de que Erlang es más rápido en la mayoría de los casos principalmente debido a una estrategia de recolección de basura diferente (por proceso), ausencia de estado compartido (subprocesos y procesos en b / w) y tipos de datos más compactos. Pero me sorprendió mucho cuando encontré comparaciones de muestras matemáticas de Erlang vs Java donde Erlang es más lento en varios pedidos, por ejemplo, de x10 a x100.

Incluso en tareas concurrentes, tanto en varios núcleos como en uno solo.

¿Cuáles son las razones para eso? Estas respuestas vinieron a la mente:

  • Uso de primitivas de Java (=> no heap / gc) en la mayoría de las tareas
  • El mismo número de subprocesos en el código Java y en los procesos Erlang, por lo que el modelo de actor no tiene ninguna ventaja aquí
  • O simplemente que Java se escribe estáticamente, mientras que Erlang no es
  • ¿Algo más?

Si eso se debe a que estos son algoritmos matemáticos muy específicos, ¿puede alguien mostrar más pruebas de rendimiento reales / prácticas?

ACTUALIZACIÓN: Hasta ahora tengo las respuestas que resumen que Erlang no es la herramienta adecuada para un "caso de Java rápido" específico, pero lo que no me queda claro es cuál es la razón principal de esta ineficiencia de Erlang aquí: tipografía dinámica, GC ¿O pobre compilación nativa?


El hecho de que erlang tenga que asignar memoria para cada valor mientras que en java normalmente reutilizará las variables si quiere que sea rápido, lo que significa que siempre será más rápido para los puntos de referencia de "bucle cerrado".

Sería interesante comparar una versión de Java con la bandera de cliente y los primitivos en caja y compararla con Erlang.

Creo que usar hipe es injusto ya que no es un proyecto activo. Me interesaría saber si algún software de misión crítica se está ejecutando en esto.


Erlang no fue construido para las matemáticas. Fue creado teniendo en cuenta la comunicación, el procesamiento paralelo y la escalabilidad, por lo que realizar pruebas de tareas matemáticas es un poco como probar si su martillo neumático le brinda una experiencia de masaje refrescante.

Dicho esto, comencemos un poco:
Si desea una programación estilo Erlang en JVM, eche un vistazo a Scala Actors o Akka framework o Vert.x.


La solución Erlang utiliza ETS, Erlang Term Storage, que es como una base de datos en memoria que se ejecuta en un proceso separado. Como consecuencia de estar en un proceso separado, todos los mensajes hacia y desde ese proceso deben ser serializados / deserializados. Esto debería explicar gran parte de la lentitud, debería pensar. Por ejemplo, si observa el punto de referencia "regex-dna", Erlang es solo un poco más lento que Java allí, y no usa ETS.


Los puntos de referencia nunca son buenos para decir algo más que lo que realmente están probando. Si cree que un punto de referencia solo está probando primitivas y un modelo de subprocesamiento clásico, de eso se trata el conocimiento. Ahora puede con cierta confianza decir que Java es más rápido que Erlang en matemáticas en primitivos, así como en el modelo clásico de subprocesos para ese tipo de problemas. No sabe nada sobre el rendimiento con una gran cantidad de subprocesos o por problemas más complicados porque el punto de referencia no lo probó.

Si está haciendo los tipos de matemáticas que probó el punto de referencia, vaya con Java porque obviamente es la herramienta adecuada para ese trabajo. Si desea hacer algo altamente escalable con poco o ningún estado compartido, encuentre un punto de referencia para eso o al menos reevalúe Erlang.

Si realmente necesita hacer cálculos pesados ​​en Erlang, considere usar HiPE (considérelo de todos modos).


Me interesé por esto ya que algunos de los puntos de referencia son un ajuste perfecto para erlang, como la secuenciación de genes. Así que en http://benchmarksgame.alioth.debian.org/ lo primero que hice fue mirar implementaciones de complemento inverso, tanto para C como para Erlang, así como los detalles de las pruebas. Descubrí que la prueba está sesgada porque no descuenta el tiempo que tarda Erlang en iniciar la máquina virtual / w los programadores; C en forma nativa compilada se inicia mucho más rápido. La forma en que se miden esos puntos de referencia es básicamente: time erl -noshell -s revcomp5 main < revcomp-input.txt

Ahora el punto de referencia dice que Java tomó 1.4 segundos y erlang / w HiPE tomó 11. Ejecutar el código Erlang (con un solo hilo) me tomó 0.15 segundos, y si descontó el tiempo que tomó iniciar vm, la carga de trabajo real tomó solo 3000 microsegundos ( 0.003 segundos).

Por lo tanto, no tengo idea de cómo se compara ese punto de referencia, si se realiza 100 veces, entonces no tiene sentido, ya que el costo de iniciar el VM de erlang será x100. Si la entrada es mucho más larga que la dada, tendría sentido, pero no veo detalles en la página web de eso. Para hacer que los puntos de referencia sean más justos para los lenguajes administrados, haga que el código (Erlang / Java) envíe una señal de Unix al pitón (que está haciendo el punto de referencia) que haga clic en la función de inicio.

Dejando a un lado el punto de referencia, la máquina virtual erlang simplemente ejecuta el código de la máquina al final, así como la máquina virtual Java. Así que no hay forma de que una operación matemática tome más tiempo en Erlang que en Java.

En lo que Erlang es malo son los datos que necesitan mutar a menudo. Como un cifrado de bloque encadenado. Digamos que tiene los caracteres "0123456789", ahora su cifrado xors los primeros 2 caracteres por 7, luego xors los siguientes dos caracteres por el resultado de los dos primeros agregados, luego xors los 2 anteriores caracteres por los resultados de los 2 actuales restados, luego xors los siguientes 4 caracteres .. etc

Debido a que los objetos en Erlang son inmutables, esto significa que toda la matriz de caracteres debe copiarse cada vez que se muta. Es por eso que erlang tiene soporte para cosas llamadas NIFS, que es un código C al que puedes llamar para resolver este problema exacto. De hecho, todo el cifrado (ssl, aes, blowfish ..) y la compresión (zlib, ..) que se envían con Erlang se implementan en C, también hay un costo cercano a 0 asociado con llamar a C desde Erlang.

Entonces usando Erlang obtienes lo mejor de ambos mundos, obtienes la velocidad de C con el paralelismo de Erlang.

Si tuviera que implementar el complemento inverso de la manera MÁS RÁPIDA posible, escribiría el código de mutación usando C pero el código paralelo usando Erlang. Suponiendo una entrada infinita, tendría a Erlang dividido en el> <<Line/binary, ">", Rest/binary>> = read_stream Envíe el bloque al primer programador disponible a través de round robin, que consta de infinitos nodos privados en red EC2, siendo agregado en tiempo real al cluster cada milisegundo.

Luego, esos nodos invocan a C a través de NIFS para su procesamiento (C fue la implementación más rápida para complementar el reverso en cualquier sitio web), luego envía la salida al maestro de nodos para enviarla al inputer.

Para implementar todo esto en Erlang, tendría que escribir código como si estuviera escribiendo un programa de un solo hilo, me llevaría menos de un día crear este código.

Para implementar esto en Java, tendría que escribir el código de un solo hilo, tendría que tomar el golpe de rendimiento de Llamar de Administrado a No Administrado (ya que usaremos la implementación de C para el trabajo duro obviamente), y luego volver a escribir para admitir 64 núcleos. Luego, vuelva a escribirlo para admitir múltiples CPUS. Luego, vuelva a escribirlo para admitir la agrupación en clústeres. Luego, vuelva a escribirlo para solucionar problemas de memoria.

Y eso es Erlang en pocas palabras.


No sé nada acerca de Erlang, pero de todos modos esto parece ser una comparación entre manzanas y naranjas. Debe tener en cuenta que se realizó un esfuerzo considerable durante más de una década para mejorar el rendimiento de Java hasta el punto en que se encuentra hoy.

No es sorprendente (para mí) que una implementación de lenguaje realizada por voluntarios o una pequeña empresa no pueda superar ese esfuerzo.