scala vs java, performance e memória? [fechado]

Estou ansioso por investigar o Scala, e tenho uma pergunta básica para a qual não consigo encontrar uma resposta.: em geral, existe uma diferença no desempenho e uso da memória entre Scala e Java?

Author: JohnSmith, 2011-05-05

8 answers

Scala torna muito fácil usar enormes quantidades de memória sem perceber. Isto geralmente é muito poderoso, mas ocasionalmente pode ser irritante. Por exemplo, suponha que você tenha um array de strings (chamado array), e um mapa desses strings para arquivos (chamado mapping). Suponha que você quer obter todos os arquivos que estão no mapa e vêm de cadeias de comprimento maior que dois. Em Java, você pode
int n = 0;
for (String s: array) {
  if (s.length > 2 && mapping.containsKey(s)) n++;
}
String[] bigEnough = new String[n];
n = 0;
for (String s: array) {
  if (s.length <= 2) continue;
  bigEnough[n++] = map.get(s);
}
Ufa! Trabalho. Em Scala, a maneira mais compacta de fazer a mesma coisa riz:
val bigEnough = array.filter(_.length > 2).flatMap(mapping.get)
Calma! Mas, a menos que você esteja bastante familiarizado com o modo como as coleções de trabalho, o que você pode não perceber é que esta forma de fazer isso criou um extra intermédio da matriz (com filter), e um objeto extra para cada elemento da matriz (com mapping.get, que retorna uma opção). Ele também cria dois objetos de função (um para o filtro e outro para o flatMap), embora isso raramente seja uma questão importante, já que objetos de função são pequenos. Então, basicamente, a memória o uso é, em um nível primitivo, o mesmo. Mas as bibliotecas da Scala têm muitos métodos poderosos que permitem criar um enorme número de objetos (geralmente de curta duração) muito facilmente. O coletor de lixo geralmente é muito bom com esse tipo de lixo, mas se você entrar completamente alheio ao que a memória está sendo usada, você provavelmente vai ter problemas mais cedo em Scala do que Java.

Note que as linguagens de computador referenciam o código Scala do jogo, escrito num estilo semelhante ao Java, a fim de obter desempenho semelhante ao Java, e assim tem o uso de memória semelhante ao Java. Você pode fazer isso no Scala: se você escrever seu código para parecer um código Java de alto desempenho, será um código Scala de alto desempenho. (You may be able to write it in a more idiomatic Scala style and still get good performance, but it depends on the specifics.)

Devo acrescentar que, por quantidade de tempo gasto na programação, o meu código Scala é normalmente mais rápido do que o meu código Java, uma vez que em Scala posso obter o tedious not-performance-critical parts done with less effort, and spend more of my attention optimizing the algorithms and code for the performance-critical parts.

 245
Author: Rex Kerr, 2011-05-05 17:24:48

Eu sou um novo usuário, então eu não sou capaz de adicionar um comentário à resposta de Rex Kerr acima (permitindo que novos usuários para "responder", mas não "Comentário" é uma regra muito estranha btw).

Inscrevi-me simplesmente para responder à insinuação "phew, Java é tão verbosa e tão trabalhosa" da resposta popular de Rex acima. Enquanto você pode, naturalmente, escrever um código Scala mais conciso, o exemplo Java dado é claramente inchado. A maioria dos desenvolvedores Java codificariam algo assim:
List<String> bigEnough = new ArrayList<String>();
for(String s : array) {
  if(s.length() > 2 && mapping.get(s) != null) {
    bigEnough.add(mapping.get(s));
  }
}
E claro, se estivermos vou fingir que a Eclipse não faz a maior parte da digitação real para você e que cada personagem gravado realmente faz de você um programador melhor, então você poderia codificar isso:
List b=new ArrayList();
for(String s:array)
  if(s.length()>2 && mapping.get(s) != null) b.add(mapping.get(s));
Agora não só poupei o tempo que me levou a digitar nomes variáveis e chavetas (libertando-me a gastar mais 5 segundos para pensar pensamentos algorítmicos profundos), como também posso entrar no meu código em concursos de ofuscação e ganhar dinheiro extra para as férias.
 96
Author: Not Sleeping, 2012-01-02 19:03:56

Escreva o seu Scala como Java, e você pode esperar que o bytecode quase idêntico seja emitido - com métricas quase idênticas.

Escreva-o mais" idiomaticamente", com objetos imutáveis e funções de ordem superior, e será um pouco mais lento e um pouco maior. A única exceção a esta regra-de-polegar é quando se usa objetos genéricos em que o tipo params usa a anotação @specialised, isso irá criar um bytecode ainda maior que pode superar o desempenho de Java, evitando boxe / descompressão.

[[3]Também vale a pena mencionar o fato de que mais memória / Menos velocidade é uma troca inevitável quando escrever código que pode ser executado em paralelo. O código Scala idiomático é de natureza muito mais declarativa do que o código Java típico, e muitas vezes está a apenas 4 caracteres (.par) de ser totalmente paralelo.

Então se

  • o código Scala demora 1,25 x mais do que o código Java numa única linha
  • pode ser facilmente dividido em 4 núcleos (agora comum até em portáteis)
  • para um tempo de execução paralelo de (1, 24 / 4 =) 0, 3125 x o Java original
Você diria então que o código Scala é comparativamente 25% mais lento, ou 3x mais rápido?

A resposta correcta depende exactamente de como define "desempenho":)

 63
Author: Kevin Wright, 2011-05-05 17:41:47
Jogo De Benchmarks Em Linguagem De Computador:

Ensaio de Velocidade java / scala 1.71 / 2.25

Teste de memória java / scala 66.55 / 80.81

Então, estes benchmarks dizem que java é 24% mais rápido e scala usa 21% mais memória.

All-in-all não é grande coisa e não deve importar em aplicativos do mundo real, onde a maior parte do tempo é consumido por banco de dados e rede.

Conclusão: mais produtivo, então você deve ir em frente.

 29
Author: Peter Knego, 2016-06-01 18:16:50
Outros responderam a esta pergunta com respeito a laços estreitos, embora pareça haver uma diferença óbvia de desempenho entre os exemplos de Rex Kerr que comentei. Esta resposta destina-se realmente a pessoas que podem investigar a necessidade de otimização em circuito fechado como falha de projeto. Sou relativamente novo no Scala (cerca de um ano), mas a sensação disso, até agora, é que ele permite a você adiarmuitos aspectos da concepção, implementação e execução relativamente fácil (com suficiente leitura de fundo e experimentação:)

Características Do Projecto Diferido:

Características De Execução Diferida:

Características de execução diferida: (desculpe, sem ligações)

  • Os valores de segurança dos fios são preguiçosos
  • passe-pelo-nome
  • coisas Monádicas
Estas características, para mim, são as que nos ajudam a trilhar o caminho para aplicações rápidas e apertadas.
Os exemplos de Rex Kerr diferem em que aspectos da execução são adiados. No exemplo Java, alocação de memória é adiada até que o seu tamanho é calculado onde o Scala o exemplo desafia a pesquisa de mapeamento. Para mim, parecem algoritmos completamente diferentes. Aqui está o que eu acho que é mais de uma maçã para maçãs equivalente para o seu exemplo Java:
val bigEnough = array.collect({
    case k: String if k.length > 2 && mapping.contains(k) => mapping(k)
})

Sem colecções intermédias, sem instâncias, etc. Isto também preserva o tipo de colecção de modo que o tipo de bigEnough é Array[File] - Array'a implementação do S collect provavelmente estará fazendo algo de acordo com o que o código Java do Sr. Kerr faz.

As características de projecto diferido acima enumeradas também permitiria que os desenvolvedores de API da coleção Scala implementassem essa implementação de coleta em versões futuras sem quebrar a API. É a isto que me refiro ao trilhar o caminho para a velocidade.

Também:

val bigEnough = array.withFilter(_.length > 2).flatMap(mapping.get)

O método withFilter que usei aqui, em vez de filter, corrige o problema da colecção intermédia, mas ainda existe a questão da opção instância.


Um exemplo de velocidade de execução simples em Scala é com log. Em Java podemos escrever algo como:
if (logger.isDebugEnabled())
    logger.debug("trace");

Em Scala, isto é apenas:

logger.debug("trace")

Porque o parâmetro de mensagem para depurar no Scala tem o tipo "=> String" que eu penso como uma função sem parâmetros que executa quando é avaliada, mas que a documentação chama de pass-by-name.

Editar { Funções em Scala são objetos por isso há um objeto extra aqui. Para o meu trabalho, o peso de um objeto trivial vale a pena remover a possibilidade de um log mensagem a ser avaliada desnecessariamente. }

Isto não torna o código mais rápido, mas torna mais provável que seja mais rápido e menos provável que tenhamos a experiência de passar e limpar o código de outras pessoas em massa. Para mim, este é um tema consistente no Scala.

O Código difícil não consegue perceber porque é que o Scala é mais rápido, embora dê uma dica.

Eu acho que é uma combinação de reutilização de código e o limite máximo de qualidade de código em Scala. Em Java, o código incrível é muitas vezes forçado a se tornar uma confusão incompreensível e por isso não é realmente viável dentro de APIs de qualidade de produção, pois a maioria dos programadores não seria capaz de usá-lo. Tenho grandes esperanças de que o Scala possa permitir que os einsteins entre nós implementem APIs muito mais competentes, potencialmente expressos através do DSLs. As APIs centrais em Scala já estão longe neste caminho.
 19
Author: Seth, 2012-05-15 05:59:48

Java e Scala compilam até JVM bytecode, então a diferença não é assim tão grande. A melhor comparação que você pode obter é provavelmente no jogo computer language benchmarks, que basicamente diz que Java e Scala ambos têm o mesmo uso de memória. Scala é apenas ligeiramente mais lento que Java em alguns dos benchmarks listados, mas isso pode ser simplesmente porque a implementação dos programas são diferentes.

A sério, estão tão perto que não vale a pena. preocupado. O aumento de produtividade que você obtém usando uma linguagem mais expressiva como Scala vale muito mais do que o desempenho mínimo (se houver) atingido.
 11
Author: ryeguy, 2016-06-01 18:54:17

@higherkinded s presentation on the subject - Scala Performance Considerations which does some Java / Scala comparisions.

Ferramentas:

Grande blogpost:

 10
Author: oluies, 2014-05-07 20:19:10

O exemplo Java não é realmente um idioma para programas de aplicação típicos. Tal código otimizado pode ser encontrado em um método de biblioteca de Sistema. Mas então ele usaria um array do tipo certo, ou seja, arquivo [] e não lançaria um IndexOutOfBoundsException. (Diferentes condições de filtragem para a contagem e adição). Minha versão seria (sempre!) com Chavetas porque eu não gosto de passar uma hora Procurando um bug que foi introduzido por salvar os 2 segundos para bater uma única tecla em Eclipse):

List<File> bigEnough = new ArrayList<File>();
for(String s : array) {
  if(s.length() > 2) {
    File file = mapping.get(s);
    if (file != null) {
      bigEnough.add(file);
    }
  }
}
Mas eu poderia trazer muitos outros exemplos de código Java do meu projeto atual. Tentei evitar o estilo comum de copiar e modificar a codificação, tendo em conta as estruturas e o comportamento comuns. Na minha classe base abstrata Dao, tenho uma classe interna abstrata para o mecanismo de caching comum. Para cada tipo de objeto de modelo concreto existe uma subclasse da classe base abstrata Dao, na qual a classe interna é subclassificada para fornecer uma implementação para o método que cria o objecto comercial quando é carregado a partir da base de dados. (Não podemos usar uma ferramenta ORM porque acessamos outro sistema através de uma API proprietária.)

Este código de subclassagem e instanciação não é claro em Java e seria muito legível em Scala.

 4
Author: MickH, 2012-10-28 21:36:49