Velocidade de compilação Java vs velocidade de compilação Scala


101

Eu tenho programado em Scala por um tempo e gosto disso, mas uma coisa que me incomoda é o tempo que leva para compilar programas. Parece uma coisa pequena, mas com Java eu ​​poderia fazer pequenas alterações em meu programa, clicar no botão executar no netbeans e BOOM, ele está rodando, e com o tempo a compilação em scala parece consumir muito tempo. Ouvi dizer que, em muitos projetos grandes, uma linguagem de script se torna muito importante por causa do tempo que leva para compilar, uma necessidade que não vi surgindo quando estava usando Java.

Mas estou vindo de Java que, pelo que entendi, é mais rápido do que qualquer outra linguagem compilada, e é rápido por causa dos motivos que mudei para Scala (é uma linguagem muito simples).

Então, eu queria perguntar, posso fazer o Scala compilar mais rápido e o scalac será sempre tão rápido quanto o javac.


Parece que alguns usuários concordam com você;) twitter.com/etorreborre/status/21286172202
VonC

Go compila mais rápido do que Java. Muito mais rápido, o que significa algo.
Daniel C. Sobral de

Ahaha, no meu caso leva vários minutos para a compilação do scalac médio com poucos LOC, fsc é um pouco mais rápido.
Jeriho

Respostas:


57

O compilador Scala é mais sofisticado que o Java, fornecendo inferência de tipos, conversão implícita e um sistema de tipos muito mais poderoso. Esses recursos não vêm de graça, então eu não esperaria que o scalac fosse tão rápido quanto o javac. Isso reflete uma compensação entre o programador que faz o trabalho e o compilador que faz o trabalho.

Dito isso, os tempos de compilação já melhoraram visivelmente indo do Scala 2.7 para o Scala 2.8, e espero que as melhorias continuem agora que a poeira baixou no 2.8. Esta página documenta alguns dos esforços e ideias em andamento para melhorar o desempenho do compilador Scala.

Martin Odersky fornece muito mais detalhes em sua resposta.



Mudei de netbeans para ant + jedit (eu sei, eu sei, formiga é para homens das cavernas, mas vou evoluir no meu próprio tempo) para que eu possa usar fsc. Mas eu estava me perguntando, como a velocidade de compilação do Clojure se compara ao Scala? Parece ter muitos dos recursos do Scala, mas imagino que a sintaxe seja muito mais fácil de analisar.
user405163

1
Estamos meio que saindo do assunto aqui, mas o compilador do Clojure é incrivelmente rápido (muito mais rápido do que javac em fontes equivalentes). Você está certo que é uma linguagem muito simples, e não tem nenhum tipo de sistema de tipo estático, o que ajuda um pouco.
Daniel Spiewak

458

Existem dois aspectos na (falta de) velocidade do compilador Scala.

  1. Maior sobrecarga de inicialização

    • O próprio Scalac consiste em um monte de classes que devem ser carregadas e compiladas por jit

    • O Scalac tem que pesquisar o classpath para todos os pacotes e arquivos raiz. Dependendo do tamanho do seu caminho de classe, isso pode levar de um a três segundos extras.

    No geral, espere uma sobrecarga de inicialização de scalac de 4-8 segundos, mais se você executá-lo pela primeira vez, de forma que os caches de disco não sejam preenchidos.

    A resposta do Scala para a sobrecarga de inicialização é usar fsc ou fazer construção contínua com sbt. O IntelliJ precisa ser configurado para usar qualquer uma das opções, caso contrário, sua sobrecarga, mesmo para arquivos pequenos, é excessivamente grande.

  2. Velocidade de compilação mais lenta. O Scalac gerencia cerca de 500 a 1000 linhas / s. Javac consegue cerca de 10 vezes isso. Há várias razões para isso.

    • A inferência de tipo é cara, principalmente se envolver pesquisa implícita.

    • O Scalac tem que fazer a verificação de tipo duas vezes; uma vez de acordo com as regras do Scala e uma segunda vez após o apagamento de acordo com as regras do Java.

    • Além da verificação de tipo, há cerca de 15 etapas de transformação para ir de Scala para Java, que levam tempo.

    • Scala normalmente gera muito mais classes por tamanho de arquivo determinado do que Java, em particular se idiomas funcionais são muito usados. A geração de bytecode e a escrita de classes levam tempo.

    Por outro lado, um programa Scala de 1000 linhas pode corresponder a um programa Java de 2-3K linhas, portanto, parte da velocidade mais lenta quando contada em linhas por segundo deve ser balanceada com mais funcionalidade por linha.

    Estamos trabalhando para melhorar a velocidade (por exemplo, gerando arquivos de classe em paralelo), mas não se pode esperar milagres nessa frente. Scalac nunca será tão rápido quanto javac. Acredito que a solução estará na compilação de servidores como o fsc em conjunto com uma boa análise de dependência, de modo que apenas o conjunto mínimo de arquivos precise ser recompilado. Estamos trabalhando nisso também.


1
Sobre a sobrecarga de inicialização devido ao carregamento de classe: a compilação antecipada para código nativo usando GCJ ou Mono ajudaria?
Caracol mecânico de

15
E se Scala fosse reescrito em C ++? : o)
marcus

Haveria um benefício em usar a instrução bytecode invokedynamic?
Rob Grant

40

Você deve estar ciente de que a compilação Scala leva pelo menos uma ordem de magnitude mais do que Java para ser compilada. Os motivos para isso são os seguintes:

  1. Convenções de nomenclatura (um arquivo XY.scalanão precisa conter uma classe chamada XYe pode conter várias classes de nível superior). O compilador pode, portanto, ter que pesquisar mais arquivos de origem para encontrar um determinado identificador de classe / característica / objeto.
  2. Implícitos - o uso pesado de implícitos significa que o compilador precisa pesquisar qualquer conversão implícita no escopo para um determinado método e classificá-los para encontrar o "correto". ( ou seja, o compilador tem um domínio de pesquisa enormemente aumentado ao localizar um método. )
  3. O sistema de tipos - o sistema de tipos scala é muito mais complicado do que o de Java e, portanto, leva mais tempo de CPU.
  4. Inferência de tipo - a inferência de tipo é computacionalmente cara e um trabalho que javacnão precisa ser feito
  5. scalacinclui um simulador de 8 bits de uma estação de batalha totalmente armada e operacional, visível usando a combinação de teclas mágicas CTRL-ALT-F12 durante a fase de compilação do GenICode .

3
@obox_lakes, odeio a procurar defeitos, mas Java faz necessidade de fazer inferência de tipos de métodos parametrizados int a<T>(T a) {}e depois a(pls_infer_my_type). james-iry.blogspot.com/2009/04/…
Elazar Leibovich

13
@Elazar - sim, eu sei. Mas é francamente ridículo, próximo a scala, chamar isso de "inferência de tipo"!
oxbow_lakes


19

A melhor forma de fazer Scala é com IDEA e SBT. Configure um projeto SBT elementar (que ele fará por você, se quiser) e execute-o no modo de compilação automática (comando ~compile) e quando você salvar seu projeto, o SBT o recompilará.

Você também pode usar o plug-in SBT para IDEA e anexar uma ação SBT a cada uma de suas configurações de execução. O plug-in SBT também oferece um console SBT interativo dentro do IDEA.

De qualquer forma (SBT rodando externamente ou plug-in SBT), o SBT permanece rodando e assim todas as classes usadas na construção do seu projeto são "aquecidas" e JIT-ed e o overhead de inicialização é eliminado. Além disso, o SBT compila apenas os arquivos de origem que precisam dele. É de longe a maneira mais eficiente de construir programas Scala.


9

As últimas revisões do Scala-IDE (Eclipse) são muito melhores no gerenciamento de compilação incremental.

Consulte “ Qual é o melhor sistema de compilação Scala? ” Para mais informações.


A outra solução é integrar fsc - Compilador offline rápido para a linguagem Scala 2 - (conforme ilustrado nesta postagem do blog ) como um construtor em seu IDE.

texto alternativo

Mas não diretamente no Eclipse, como Daniel Spiewak menciona nos comentários:

Você não deve usar o FSC diretamente no Eclipse, apenas porque o Eclipse já está usando o FSC sob a superfície.
O FSC é basicamente uma camada fina sobre o compilador residente, que é precisamente o mecanismo usado pelo Eclipse para compilar projetos Scala.


Finalmente, como Jackson Davis me lembra nos comentários:

sbt (ferramenta de construção simples) também inclui algum tipo de compilação "incremental" (por meio de execução acionada ), embora não seja perfeita , e a compilação incremental aprimorada está em andamento para a próxima versão 0.9 sbt.


2
sbt também pode fazer compilações incrementais
Jackson Davis

@Jackson: execução acionada, certo! Eu incluí na minha resposta.
VonC de

2
Você não deve usar o FSC diretamente no Eclipse, apenas porque o Eclipse está usando o FSC sob a superfície. O FSC é basicamente uma camada fina sobre o compilador residente, que é precisamente o mecanismo usado pelo Eclipse para compilar projetos Scala.
Daniel Spiewak

1
FSC significa Fast Scala Compiler - não Fast Java Compiler
Ben McCann

@BenMcCann: ops. Certo. Eu consertei a resposta.
VonC

6

Use fsc - é um compilador de scala rápido que fica como uma tarefa em segundo plano e não precisa ser carregado o tempo todo. Ele pode reutilizar a instância do compilador anterior.

Não tenho certeza se o plug-in Scala do Netbeans suporta fsc (a documentação diz isso), mas não consegui fazer funcionar. Experimente compilações noturnas do plugin.


1
O plugin IntelliJ IDEA Scala também tem a opção de usar fsc
Aaron Novstrup

1
@anovstrup: sim, mas às vezes trava.
Denis Tulskiy

4

Você pode usar o plugin JRebel, que é gratuito para Scala. Assim, você pode "desenvolver no depurador" e o JRebel sempre recarregará a classe alterada no local.

Eu li alguma declaração em algum lugar do próprio Martin Odersky onde ele está dizendo que as buscas por implícitos (o compilador deve se certificar de que não há mais de um implícito único para a mesma conversão para descartar ambigüidades) podem manter o compilador ocupado. Portanto, pode ser uma boa ideia lidar com os implícitos com cuidado.

Se não precisa ser 100% Scala, mas também algo semelhante, você pode dar Kotlin experimentar o .

- Oliver


2

Tenho certeza de que isso terá uma votação negativa, mas a reversão extremamente rápida nem sempre conduz à qualidade ou à produtividade.

Reserve um tempo para pensar com mais cuidado e executar menos microciclos de desenvolvimento. O bom código Scala é mais denso e essencial (ou seja, livre de detalhes incidentais e complexidade). Exige mais reflexão e isso leva tempo (pelo menos no início). Você pode progredir bem com menos ciclos de código / teste / depuração que são individualmente um pouco mais longos e ainda melhorar sua produtividade e a qualidade de seu trabalho.

Resumindo: Procure um padrão de trabalho ideal mais adequado ao Scala.


3
Concordo que não é essencial ter um ciclo de reversão rápido. Mas não dói, não é?
Elazar Leibovich

27
Não vou votar contra, mas dizer que você deve ajustar seu padrão de trabalho às limitações de sua ferramenta (a velocidade lenta do compilador) em vez de tentar melhorar a ferramenta não é um bom argumento. Especialmente a capacidade de fazer ciclos de teste rápidos é muito valiosa (embora não substitua a necessidade de pensar profundamente, o tipo que provavelmente é melhor feito longe do teclado, ela o complementa muito bem).
Thilo de

9
Acho que a maior parte da minha produtividade é perdida pensando demais antes de correr. Freqüentemente me pego olhando para alguma equação por longos períodos tentando localizar qualquer armadilha em potencial que está esperando por mim, enquanto penso: "Basta executá-la!" na parte de trás da minha cabeça. E com certeza, quando executo o programa, aprendo muito mais do que provavelmente aprenderia com mais uma ou duas horas de meditação. A meditação é boa, mas sinto que tive um uso ótimo da compilação / meditação incremental com java.
user405163

2
Isso também é semelhante a sugerir que Shakespeare não deveria usar um corretor ortográfico e, em vez disso, pensar mais sobre o que ele quer dizer. O corretor ortográfico automatizado ajuda com um conjunto de problemas completamente diferente.
Thilo de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.