BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Notícias Benchmarking de Streams e Lambdas do Java 8

Benchmarking de Streams e Lambdas do Java 8

Favoritos

A primeira versão da postagem "How Misusing Streams Can Make Your Code 5 Times Slower" no blog Takipi, recebeu criticas sobre o baixo desempenho dos benchmarking das Streams do Java 8, que foram rapidamente retificados com uma versão otimizada do benchmark original atribuindo os resultados corretos.

Com a ajuda dos Streams e Lambdas do Java 8, os desenvolvedores Java podem utilizar o estilo de programação funcional, que é diferente da programação com os tradicionais laços for e Iterators. (O InfoQ já mostrou previamente o estilo funcional contra o estilo imperativo do Java 8.)

A postagem no blog Takipi testou as funcionalidades da programação funcional do Java 8 usando como exemplo a busca do maior valor em um ArrayList. O teste compara o estilo de programação funcional versus imperativo através da implementação de Iterators, For-loops, For-Each loops, Stream, parallel Stream, e Lambdas (com e sem For-Each). A primeira iteração desse benchmarking falhou em usar algumas otimizações básicas do compilador JIT e em alguns casos um pouco de otimização foi utilizada para alguns casos de testes enquanto os demais não receberam os benefícios das otimizações.

Seguindo as criticas da comunidade, Takipi rapidamente revisou seu benchmark (construído com JMH - O Java Microbenchmarking Harness). A primeira grande mudança no benchmark revisado foi a remoção da palavra reservada volatile para os atributos "integers" como mostrado a seguir:

-    volatile List<Integer> integers = null;

+    List<Integer> integers = null;

Sergey Kuksenko, engenheiro de desempenho do Java na Oracle, apontou a mudança anterior, pois ajuda o compilador JIT a usar a otimização de "eliminação da verificação de intervalos".

A segunda grande mudança foi a eliminação do auto-boxing, já que o benchmark pode encontrar problemas de auto-boxing com Streams. A mudança foi feita em diversos pontos do código. Uma das grandes mudanças é apresentada no trecho de código a seguir:

-    Optional<Integer> max = integers.stream().reduce(Integer::max);

-    return max.get();

+    return integers.stream().mapToInt(Integer::intValue).reduce(Integer.MIN_VALUE, Integer::max);

O benchmarking revisado demonstra que o Stream em paralelo tem uma ligeira vantagem sobre os outros casos de testes; mas no geral o grupo de testes no estilo de programação imperativo venceu o grupo de testes de estilo de programação funcional quando os casos de uso são tão pequenos quanto a interação em um ArrayList para encontrar o valor máximo.

O InfoQ americano contatou o autor do blog, Alex Zhitnitsky que mencionou:

Há muito entusiamos sobre as novas funcionalidades do Java 8, que é ótimo, mas muitos desenvolvedores usam essas funcionalidades de modo incorreto. Durante o benchmarking dos casos de uso, queríamos mostrar uma versão do benchmark não otimizada, já que no dia a dia muitos desenvolvedores utilizam essas funcionalidades de diversas maneiras.

A postagem apresenta um caso de uso em especifico que favorece os laços, quando comparado com uma implementação desleixada porém curta/intuitiva/rápida de streams. Por exemplo:

integers.stream().reduce(Integer::max);

versus

integers.stream().mapToInt(Integer::intValue).reduce(Integer.MIN_VALUE, Integer::max);

A segunda implementação é o modo correto para obter a otimização no benchmark, embora o mapToInt possa ser facilmente esquecido criando um problema com o auto-boxing com a implementação mais curta. Ambos os benchmarks estão corretos, já que são medidas de implementações legitimas - Mesmo que a primeira versão não contenha as otimizações do JIT (que podem não ser intuitivas e longas, como nesse exemplo do mapToInt).

O importante deste exercício é demonstrar o quão importante é conhecer o que está sendo analisado para entender e comparar o código gerado especialmente quando trata-se de microbenchmarks.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

BT