Puede escribir código rápido o lento en cualquier idioma :-)
Sobre la base de una inspección rápida de una parte del código Clojure, diría que la principal razón para la diferencia de rendimiento es que el código de referencia Clojure aún no se ha optimizado completamente para usar las funciones de idioma más rápidas disponibles.
Por ejemplo las siguientes características en Clojure son todos muy fresco y útil para la conveniencia del desarrollo, pero incurren en alguna sobrecarga de rendimiento en tiempo de ejecución:
- secuencias perezosos y listas
- dinámico de Java interoperabilidad mediante reflexión
- tiempo de ejecución función composición/funciones de primera clase
- Multimétodos/envío dinámico
- compilación dinámica con eval o en el REPL
- BigInteger aritmética
Si quieres absoluta de rendimiento máximo (a costa de cierta complejidad adicional), desea volver a escribir código para evitar estos y usar cosas como:
- insinuación de tipo estático (para evitar la reflexión)
- Transitorios
- macros (para la manipulación de código de tiempo de compilación)
- Protocolos
- primitivos de Java y matrices
- bucle/repiten para la iteración
Con el uso juicioso de lo anterior, he encontrado que por lo general es posible llegar muy cerca de rendimiento de Java en Clojure 1.2+, por ejemplo, considere el siguiente código para hacer un millón de adiciones:
Desobligado Clojure usando una secuencia perezosa y una aritmética de biginterger. Es agradable y funcional pero no es especialmente rápido:
(reduce
(fn [acc val] (unchecked-int (unchecked-add (int acc) (int val))))
(range 0 1000000))
=> "Elapsed time: 65.201243 msecs"
optimizado Clojure con la aritmética primitiva y el lazo/Repetir:
(loop [acc (int 0) i (int 0)]
(if (>= i (int 1000000))
acc
(recur (unchecked-add acc i) (unchecked-inc i))))
=> "Elapsed time: 0.691474 msecs"
Java código, un bucle iterativo bastante estándar:
public static int addMillion() {
int result=0;
for (int i=0; i<1000000; i++) {
result+=i;
}
return result;
}
=> "Elapsed time: 0.692081 msecs"
ps He usado unchecked-add en lugar de + en el código Clojure para que coincida con el comportamiento de desbordamiento de enteros de Java.
Se agregó una etiqueta de "rendimiento", ya que es donde se encuentran la mayoría de las preguntas como esta. –
Clojure aún no está cocinado - Clojure 1.0 fue lanzado en mayo de 2009, el primer lanzamiento público de Scala fue en 2003. – igouy