Velocidad de compilación de Java vs velocidad de compilación de Scala

101

He estado programando en Scala por un tiempo y me gusta, pero una cosa que me molesta es el tiempo que lleva compilar los programas. Parece una cosa pequeña, pero con Java podría hacer pequeños cambios en mi programa, hacer clic en el botón Ejecutar en netbeans y BOOM, se está ejecutando y, con el tiempo, la compilación en Scala parece consumir mucho tiempo. Escuché que con muchos proyectos grandes, un lenguaje de scripting se vuelve muy importante debido al tiempo que toma compilar, una necesidad que no vi surgir cuando estaba usando Java.

Pero vengo de Java que, según tengo entendido, es más rápido que cualquier otro lenguaje compilado y es rápido por las razones por las que cambié a Scala (es un lenguaje muy simple).

Así que quería preguntar, ¿puedo hacer que Scala compile más rápido? ¿Scalac alguna vez será tan rápido como javac?

user405163
fuente
Parece que algunos usuarios están de acuerdo contigo;) twitter.com/etorreborre/status/21286172202
VonC
Go compila más rápido que Java. Mucho más rápido, que es decir algo.
Daniel C. Sobral
Ahaha, en mi caso se necesitan varios minutos para una compilación de scalac promedio con pocos LOC, fsc es un poco más rápido.
Jeriho

Respuestas:

57

El compilador de Scala es más sofisticado que el de Java y proporciona inferencia de tipos, conversión implícita y un sistema de tipos mucho más potente. Estas funciones no son gratuitas, por lo que no esperaría que scalac sea tan rápido como javac. Esto refleja una compensación entre el programador que hace el trabajo y el compilador que lo hace.

Dicho esto, los tiempos de compilación ya han mejorado notablemente al pasar de Scala 2.7 a Scala 2.8, y espero que las mejoras continúen ahora que el polvo se ha asentado en 2.8. Esta página documenta algunos de los esfuerzos e ideas en curso para mejorar el rendimiento del compilador Scala.

Martin Odersky proporciona muchos más detalles en su respuesta.

Aaron Novstrup
fuente
1
¿No es más esta página ( lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded )?
VonC
He cambiado de netbeans a ant + jedit (lo sé, lo sé, ant es para hombres de las cavernas, pero evolucionaré en mi propio tiempo) para poder usar fsc. Pero me preguntaba, ¿cómo se compara la velocidad de compilación de Clojure con Scala? Parece tener muchas de las características de Scala, pero imagino que la sintaxis es mucho más fácil de analizar.
user405163
1
Nos estamos saliendo del tema aquí, pero el compilador de Clojure es increíblemente rápido (mucho más rápido que javac en fuentes equivalentes). Sin embargo, tienes razón en que es un lenguaje realmente simple y no tiene ningún tipo de sistema de tipo estático, lo que ayuda bastante.
Daniel Spiewak
458

Hay dos aspectos de la (falta de) velocidad del compilador de Scala.

  1. Mayor sobrecarga de inicio

    • Scalac en sí mismo consta de MUCHAS clases que deben cargarse y compilarse con jit

    • Scalac tiene que buscar en la ruta de clases todos los paquetes y archivos raíz. Dependiendo del tamaño de su classpath, esto puede llevar de uno a tres segundos adicionales.

    En general, espere una sobrecarga de inicio de scalac de 4 a 8 segundos, más si lo ejecuta la primera vez para que las memorias caché de disco no se llenen.

    La respuesta de Scala a la sobrecarga de inicio es usar fsc o hacer una construcción continua con sbt. IntelliJ debe configurarse para usar cualquiera de las opciones; de lo contrario, su sobrecarga, incluso para archivos pequeños, es irrazonablemente grande.

  2. Velocidad de compilación más lenta. Scalac gestiona entre 500 y 1000 líneas / seg. Javac gestiona alrededor de 10 veces eso. Hay varias razones para esto.

    • La inferencia de tipos es costosa, en particular si implica una búsqueda implícita.

    • Scalac tiene que comprobar el tipo dos veces; una vez según las reglas de Scala y una segunda vez después del borrado según las reglas de Java.

    • Además de la verificación de tipos, hay alrededor de 15 pasos de transformación para pasar de Scala a Java, que llevan tiempo.

    • Scala generalmente genera muchas más clases por tamaño de archivo dado que Java, en particular si se usan mucho los modismos funcionales. La generación de códigos de bytes y la escritura de clases lleva tiempo.

    Por otro lado, un programa Scala de 1000 líneas podría corresponder a un programa Java de 2-3K líneas, por lo que parte de la velocidad más lenta cuando se cuenta en líneas por segundo tiene que equilibrarse con más funcionalidad por línea.

    Estamos trabajando en mejoras de velocidad (por ejemplo, generando archivos de clases en paralelo), pero no se pueden esperar milagros en este frente. Scalac nunca será tan rápido como javac. Creo que la solución estará en servidores de compilación como fsc junto con un buen análisis de dependencias para que solo se tenga que volver a compilar el conjunto mínimo de archivos. También estamos trabajando en eso.

Martin Odersky
fuente
1
Acerca de la sobrecarga de inicio debido a la carga de clases: ¿ayudaría la compilación anticipada en código nativo usando GCJ o Mono?
Caracol mecánico
15
¿Y si Scala se reescribiera en C ++? : o)
marcus
¿Sería beneficioso utilizar la instrucción de código de bytes dinámico invocado?
Rob Grant
40

Debe tener en cuenta que la compilación de Scala tarda al menos un orden de magnitud más que Java en compilarse. Las razones de esto son las siguientes:

  1. Convenciones de nomenclatura (un archivo de XY.scalaarchivo no necesita contener una clase llamada XYy puede contener múltiples clases de nivel superior). Por lo tanto, el compilador puede tener que buscar más archivos fuente para encontrar un identificador de clase / rasgo / objeto dado.
  2. Implicitos: el uso intensivo de implícitos significa que el compilador necesita buscar cualquier conversión implícita dentro del alcance para un método dado y clasificarlos para encontrar el "correcto". ( es decir, el compilador tiene un dominio de búsqueda masivamente incrementado cuando localiza un método ) .
  3. El sistema de tipos: el sistema de tipos scala es mucho más complicado que el de Java y, por lo tanto, requiere más tiempo de CPU.
  4. Inferencia de tipo: la inferencia de tipo es computacionalmente costosa y un trabajo que javacno es necesario realizar en absoluto
  5. scalacincluye un simulador de 8 bits de una estación de batalla completamente armada y operativa, visible utilizando la combinación de teclas mágicas CTRL-ALT-F12 durante la fase de compilación de GenICode .
oxbow_lakes
fuente
3
@obox_lakes, odio que pequeñez, pero Java hace necesario hacer la inferencia de tipos de métodos con parámetros int a<T>(T a) {}y, a continuación a(pls_infer_my_type). james-iry.blogspot.com/2009/04/…
Elazar Leibovich
13
@Elazar - sí, lo sé. ¡Pero es francamente ridículo, al lado de scala, llamar a esto "inferencia de tipos"!
oxbow_lakes
19

La mejor forma de hacer Scala es con IDEA y SBT. Configure un proyecto SBT elemental (que lo hará por usted, si lo desea) y ejecútelo en modo de compilación automática (comando ~compile) y cuando guarde su proyecto, SBT lo recompilará.

También puede utilizar el complemento SBT para IDEA y adjuntar una acción SBT a cada una de sus configuraciones de ejecución. El complemento SBT también le brinda una consola SBT interactiva dentro de IDEA.

De cualquier manera (SBT ejecutándose externamente o complemento SBT), SBT permanece ejecutándose y, por lo tanto, todas las clases utilizadas en la construcción de su proyecto se "calientan" y JIT-ed y se elimina la sobrecarga inicial. Además, SBT compila solo los archivos fuente que lo necesitan. Es, con mucho, la forma más eficaz de crear programas Scala.

Randall Schulz
fuente
9

Las últimas revisiones de Scala-IDE (Eclipse) son mucho mejores para administrar la compilación incremental.

Consulte " ¿Cuál es el mejor sistema de compilación de Scala? " Para obtener más información.


La otra solución es integrar fsc (compilador rápido fuera de línea para el lenguaje Scala 2 ) (como se ilustra en esta publicación de blog ) como constructor en su IDE.

texto alternativo

Pero no directamente en Eclipse, como menciona Daniel Spiewak en los comentarios:

No debería usar FSC dentro de Eclipse directamente, aunque solo sea porque Eclipse ya está usando FSC bajo la superficie.
FSC es básicamente una capa delgada sobre el compilador residente, que es precisamente el mecanismo utilizado por Eclipse para compilar proyectos de Scala.


Finalmente, como Jackson Davis me recuerda en los comentarios:

sbt (Simple build Tool) también incluye algún tipo de compilación "incremental" (a través de ejecución activada ), aunque no es perfecta , y la compilación incremental mejorada está en proceso para la próxima versión 0.9 sbt.

VonC
fuente
2
sbt también puede hacer compilaciones incrementales
Jackson Davis
@Jackson: ejecución activada, ¿verdad? Lo he incluido en mi respuesta.
VonC
2
No debería usar FSC dentro de Eclipse directamente, aunque solo sea porque Eclipse ya está usando FSC bajo la superficie. FSC es básicamente una capa delgada sobre el compilador residente, que es precisamente el mecanismo utilizado por Eclipse para compilar proyectos de Scala.
Daniel Spiewak
1
FSC son las siglas de Fast Scala Compiler - no Fast Java Compiler
Ben McCann
@BenMcCann: ¡Ups! Correcto. He arreglado la respuesta.
VonC
6

Use fsc : es un compilador de Scala rápido que se encuentra como una tarea en segundo plano y no necesita cargarse todo el tiempo. Puede reutilizar la instancia del compilador anterior.

No estoy seguro de si el complemento Scala de Netbeans es compatible con fsc (la documentación lo dice), pero no pude hacerlo funcionar. Pruebe las compilaciones nocturnas del complemento.

Denis Tulskiy
fuente
1
El complemento IntelliJ IDEA Scala también tiene una opción para usar fsc
Aaron Novstrup
1
@anovstrup: sí, pero a veces falla.
Denis Tulskiy
4

Puede utilizar el complemento JRebel, que es gratuito para Scala. Así que puede "desarrollar en el depurador" y JRebel siempre recargaría la clase cambiada en el acto.

Leí una declaración en alguna parte del propio Martin Odersky donde dice que las búsquedas de implícitos (el compilador debe asegurarse de que no haya más de un solo implícito para la misma conversión para descartar ambigüedades) pueden mantener ocupado al compilador. Por lo tanto, podría ser una buena idea manejar las implicaciones con cuidado.

Si no tiene que ser 100% Scala, sino también algo similar, puede probar Kotlin .

- Oliver

OlliP
fuente
2

Estoy seguro de que esto será rechazado, pero un cambio extremadamente rápido no siempre conduce a la calidad o la productividad.

Tómese el tiempo para pensar más detenidamente y ejecutar menos microciclos de desarrollo. El buen código de Scala es más denso y esencial (es decir, libre de detalles incidentales y complejidad). Requiere más reflexión y eso lleva tiempo (al menos al principio). Puede progresar bien con menos ciclos de código / prueba / depuración que individualmente son un poco más largos y aún así mejoran su productividad y la calidad de su trabajo.

En resumen: busque un patrón de trabajo óptimo que se adapte mejor a Scala.

Randall Schulz
fuente
3
Estoy de acuerdo en que no es esencial tener un ciclo de cambio rápido. Pero no duele, ¿verdad?
Elazar Leibovich
27
No voy a rechazarlo, pero decir que debería ajustar su patrón de trabajo a las limitaciones de su herramienta (la velocidad lenta del compilador) en lugar de intentar mejorar la herramienta no es un buen argumento. Especialmente la capacidad de hacer ciclos de prueba rápidos es muy valiosa (aunque no reemplaza la necesidad de pensar en profundidad, el tipo que probablemente se hace mejor fuera del teclado, lo complementa muy bien).
Thilo
9
Creo que la mayor parte de mi productividad se pierde por pensar demasiado antes de correr. Con frecuencia me encuentro mirando alguna ecuación durante largos períodos tratando de detectar cualquier peligro potencial que me esté esperando, todo mientras pienso: "¡Ejecútelo!" en la parte de atrás de mi cabeza. Y efectivamente, cuando ejecuto el programa aprendo mucho más de lo que probablemente habría aprendido con otra hora o dos de meditación. La meditación es buena, pero creo que hice un uso muy óptimo de la compilación / meditación incremental con Java.
user405163
2
Esto también es similar a sugerir que Shakespeare no debería usar un corrector ortográfico y, en cambio, pensar más en lo que quiere decir. El corrector ortográfico automático ayuda con un conjunto de problemas completamente diferente.
Thilo