2010-08-16 7 views
93

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

Pero vengo de Java que, como yo lo entiendo, es más rápido que cualquier otro lenguaje compilado, y es rápido debido a las razones por las que cambié a Scala (es un lenguaje muy simple).

Así que quería preguntar, ¿puedo hacer que la compilación de Scala sea más rápida y que scalac sea tan rápido como javac?

+0

Parece que algunos usuarios están de acuerdo con usted;) http://twitter.com/etorreborre/status/21286172202 – VonC

+0

Ir compila más rápido que Java. Mucho más rápido, lo que está diciendo algo. –

+0

Ahaha, en mi caso toma varios minutos para la compilación scalac promedio con pocos cientos de LOC. Fsc es un poco más rápido. – Jeriho

Respuesta

54

El compilador de Scala es más sofisticado que el de Java, proporcionando inferencia de tipo, conversión implícita y un sistema de tipo mucho más potente. Estas características no son gratis, así que no esperaría que scalac fuera tan rápido como javac. Esto refleja una compensación entre el programador que hace el trabajo y el compilador que hace el trabajo.

Dicho esto, los tiempos de compilación ya han mejorado notablemente pasando 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.This page documenta algunos de los esfuerzos e ideas en curso para mejorar el rendimiento del compilador de Scala.

Martin Odersky provides much more detail in his answer.

+1

¿No es más esta página (http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/)? – VonC

+0

He cambiado de netbeans a hormiga + jedit (sé que lo sé, hormiga es para hombres de las cavernas, pero evolucionaré en mi propio tiempo) para que pueda usar fsc. Pero me preguntaba, ¿cómo se compara la velocidad de compilación de Clojure con la de 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

Estamos un poco fuera de tema aquí, pero el compilador de Clojure es increíblemente rápido (mucho más rápido que javac en fuentes equivalentes). 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. –

6

Use fsc - es un compilador scala rápido que se sienta como una tarea en segundo plano y no necesita cargar todo el tiempo. Puede reutilizar la instancia del compilador anterior.

No estoy seguro de si Netbeans scala plugin admite fsc (la documentación lo dice), pero no pude hacerlo funcionar. Pruebe las compilaciones nocturnas del complemento.

+1

El complemento IntelliJ IDEA Scala también tiene una opción para usar fsc –

+0

@anovstrup: sí, pero a veces falla. –

8

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

Consulte "What’s the best Scala build system?" para obtener más información.


La otra solución es integrar fsc - Fast offline compiler for the Scala 2 language - (como se ilustra en este blog post) como un constructor en su IDE.

alt text

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

No se debe utilizar dentro de FSC Eclipse directamente, aunque sólo sea porque Eclipse ya está utilizando 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.


Por último, como Jackson Davis me recuerda en los comentarios:

sbt (Simple build Tool) también incluir algún tipo de compilación "incrementales" (a través de triggered execution), a pesar de que is not perfect, y el aumento de la compilación incremental es en el trabajar para la próxima versión de 0.9 sbt.

+2

sbt también puede hacer compilaciones incrementales –

+0

@Jackson: ejecución desencadenada, ¡verdad! Lo he incluido en mi respuesta. – VonC

+1

No debe usar FSC directamente en Eclipse, solo porque Eclipse * ya * usa FSC debajo de la superficie. FSC es básicamente una capa delgada sobre el compilador residente, que es * precisamente * el mecanismo utilizado por Eclipse para compilar los proyectos de Scala. –

2

estoy seguro de que será votada abajo-pero extremadamente rápido vuelco no siempre es propicio para la calidad o la productividad.

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

En resumen: busque un patrón de trabajo óptimo más adecuado para Scala.

+2

Estoy de acuerdo en que no es esencial tener un ciclo rápido de vuelta. Pero no duele, ¿verdad? –

+25

No voy a votar a la baja, pero decir que debe ajustar su patrón de trabajo a las limitaciones de su herramienta (la baja velocidad del compilador) en lugar de tratar de 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 profundamente, del tipo que probablemente sea mejor eliminar del teclado, se complementa muy bien). – Thilo

+8

Creo que la mayor parte de mi productividad se pierde al pensar demasiado antes de ejecutar. Con frecuencia me encuentro mirando una ecuación durante largos períodos tratando de detectar cualquier posible escollo que me esté esperando, todo mientras pienso: "¡Solo ejecútelo!" en la parte posterior de mi cabeza. Y, por supuesto, cuando ejecuto el programa aprendo mucho más de lo que probablemente tendría con otra hora o dos de meditación. La meditación es buena, pero creo que tuve un uso muy óptimo de la compilación/meditación incremental con java. – user405163

39

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

  1. Convenciones de nombres (un archivo de archivos XY.scala no necesita contener una clase llamada XY y puede contener varias clases de nivel superior). El compilador puede, por lo tanto, tener que buscar más archivos fuente para encontrar un identificador de clase/rasgo/objeto dado.
  2. Implicits: uso intensivo de implícitos significa que el compilador necesita buscar cualquier conversión implícita en el alcance para un método dado y clasificarlos para encontrar el "correcto". (es decir, el compilador tiene un dominio de búsqueda enormemente aumentado al ubicar un método.)
  3. El sistema de tipos - el sistema de tipo scala es mucho más complicado que Java y por lo tanto requiere más tiempo de CPU.
  4. La inferencia de tipos - la inferencia de tipos es computacionalmente caro y un trabajo que javac no necesita hacer nada
  5. scalac incluye un simulador de 8 bits de una estación de batalla completamente armado y operativo, se puede ver con la combinación de teclas CTRL-magia ALT-F12 durante la fase de compilación GenICode.
+9

¡No debías hablar de la estación de batalla! –

+3

@obox_lakes, odio a nitpick, pero Java * does * necesita hacer la inferencia de tipo para los métodos parametrizados 'int a (T a) {}' y luego 'a (pls_infer_my_type)'. http://james-iry.blogspot.com/2009/04/java-has-type-inference-and-refinement.html –

+13

@Elazar - sí, lo sé. ¡Pero es francamente risible, junto a Scala, llamar a esto "inferencia tipográfica"! –

19

La mejor manera 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 volverá a compilar.

También puede usar el plug-in SBT para IDEA y adjuntar una acción SBT a cada una de las configuraciones de ejecución. El complemento SBT también le ofrece una consola interactiva SBT dentro de IDEA.

De cualquier manera (SBT ejecutándose externamente o SBT), SBT se mantiene funcionando y así todas las clases utilizadas en la construcción de su proyecto se "calientan" y JIT-ed y la sobrecarga de arranque se elimina. Además, SBT compila solo los archivos fuente que lo necesitan. Es, de lejos, la forma más eficiente de crear programas Scala.

439

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

  1. Mayor arranque sobrecarga

    • sí scalac consiste en un montón de clases que tienen que ser cargado y JIT-compilado

    • scalac tiene que buscar la ruta de clase para todos los paquetes de raíz y archivos. Dependiendo del tamaño de su classpath esto puede tomar de uno a tres segundos extra.

    En general, le espera una sobrecarga de inicio de scalac de 4-8 segundos, ya si se ejecuta la primera vez de modo de disco a almacenar en caché no se llenan.

    La respuesta de Scala a la sobrecarga de inicio consiste en usar fsc o hacer construcciones continuas con sbt. IntelliJ necesita configurarse para usar cualquiera de las opciones, de lo contrario su sobrecarga incluso para archivos pequeños es excesivamente grande.

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

    • La inferencia tipo es costosa, en particular si se trata de una búsqueda implícita.

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

    • Además del control de tipos, hay unos 15 pasos de transformación para ir de Scala a Java, lo que lleva tiempo.

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

    Por otra parte, un programa de Scala 1000 línea podría corresponder a un programa Java 2-3k línea, por lo que algunos de la velocidad más lenta cuando contado en líneas por segundo tiene que equilibrada contra más funcionalidad por línea.

    Estamos trabajando en mejoras de velocidad (por ejemplo, generando archivos de clase 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 los servidores de compilación como fsc junto con un buen análisis de dependencia para que solo se recompile el conjunto mínimo de archivos. Estamos trabajando en eso, también.

+1

Acerca de la sobrecarga de inicio debido a la carga de clases: ¿compilaría antes de tiempo el código nativo usando la ayuda de GCJ o Mono? –

+12

¿Qué pasa si Scala se reescribió en C++? : o) – marcus

+0

¿Habría algún beneficio al usar la instrucción de código de byte dinámico invocado? –

3

Puede usar el plugin JRebel que es gratuito para Scala. Así que puedes "desarrollar en el depurador" y JRebel siempre volvería a cargar la clase modificada en el acto.

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

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

- Oliver

+0

en caso de que aún no lo sepa, la respuesta de Martin está justo encima de la suya – asgs