JavaTips 3.0 – Performance Generics + AutoBox/UnBox
Março 19, 2008
AutoBox/UnBox é a conversão de forma automática entre objetos e tipos primitivos, dicas:
- Use somente quando houver “descasamento” entre tipos primitivos e objetos empacotadores
- Não abuse: um Integer não substitui um int (a performance é pior)
- Cuidado, unboxing com objetos null lança exceção
Probolema:
- Generics não trabalha com tipos primitivos
Após executar o seguinte teste de performance, constatou-se uma diferênça em média de 25% com uso do autobox. O algoritimo de teste baseou-se em comparar as duas execuções:
- faça 1000 vezes
- varra um ArrayList<Integer>, capturando o valor sem fazer autobox
- faça 1000 vezes
- varra um ArrayList<Integer> usando enhanced-loop fazendo automaticamente unbox para int, capturando o valor e fazendo autbox novamente para um objeto Integer.
Resultado da execução:
___________________________________
autoBoxUnBox()…java.lang.NullPointerException
Sem autoboxing = 6531ms
Com autobox/unbox= 8734ms
Diferença de 26%
___________________________________
Conclusão:
Se sua aplicação é “Performance Driven”, estruturas como o IntHashMap visto no blog anterior entre outras coleções da API que não trabalhem com Generics podem ser a melhor saída para escovar milisegundos de processamento.
Abaixo segue a classe usada no teste:
Java Tips 2.0: Ganhe até 70% performance com IntHashMap
Março 17, 2008
O java.util.HashMap como o próprio nome diz utiliza-se do hash code do objeto “chave” para mapear as entradas do mapa. Funciona basicamente assim:
HashMap map = new HashMap();
map.put("matricula.12345", "Fabricio");
A essência do funcionamento do método put() é :
public void put(Object key, Object value){
int hash = geraHashCode(key);
int posicao = geraPosicaoNaTabela(hash);
adicionaNaTabelaDeEntradas(posicao, value);
}
Quando porém estamos trabalhando com um mapa onde as chaves já são inteiros muitas operações do mapa podem ser simplificadas, solução: IntHashMap.
Algumas coporações como a Oracle, Apache, etc… possuem em suas “foundation classes” alguma implementações que trababalhem desta forma para obterem melhor performance. Afim de comparar o desempenho com HashMap executei dois teste simples
- Povoando o mapa com 1000000 chaves sequenciais (Puts)
- Recuperando todos os objetos do mapa (Gets), utilizou-se string como objeto para evitar autobox/unbox.
O resultado foram ganhos em média de 70% para os puts, e 30% para os gets efetuados no mapa. Veja o resultado de uma excução:
Main.testSunMap()…
Main.testIntMap()…
‘Puts’ execution time (milliseconds):
sunMap: 3328 intMap: 922, Percentage of gain: 73%
‘Gets’ execution time (milliseconds):
sunMap: 234 intMap: 140, Percentage of gain: 41%
Conclusão
Se suas chaves são inteiros use IntHashMap. Os resultados foram obtidos usando java 5, o mesmo exemplo foi executado com 1.4 e obteve em média os mesmos valores, no entanto se em sua aplicação você não tomar os devidos cuidados no uso do autoboxing/unboxing de valores primitivos para objetos, a diferença de ganho vai ser ainda em muito melhor para o IntHashMap devido a perda de performance executando o boxing.