Por que "while (i ++ <n) {}" é significativamente mais lento que "while (++ i <n) {}"
Aparentemente, no meu laptop Windows 8 com HotSpot JDK 1.7.0_45 (com todas as opções de compilador / VM definidas como padrão), o loop abaixo
final int n = Integer.MAX_VALUE;
int i = 0;
while (++i < n) {
}
é pelo menos 2 ordens de magnitude mais rápido (~ 10 ms vs. ~ 5000 ms) do que:
final int n = Integer.MAX_VALUE;
int i = 0;
while (i++ < n) {
}
Por acaso, notei esse problema enquanto escrevia um loop para avaliar outro problema de desempenho irrelevante. E a diferença entre++i < n
ei++ < n
foi enorme o suficiente para influenciar significativamente o resultado.
Se olharmos para o bytecode, o corpo do loop da versão mais rápida é:
iinc
iload
ldc
if_icmplt
E para a versão mais lenta:
iload
iinc
ldc
if_icmplt
Então para++i < n
, primeiro incrementa a variável locali
por 1 e empurre-o para a pilha de operandos enquantoi++ < n
executa essas duas etapas na ordem inversa. Mas isso não parece explicar por que o primeiro é muito mais rápido. Existe alguma cópia temporária envolvida neste último caso? Ou é algo além do bytecode (implementação de VM, hardware etc.) que deve ser responsável pela diferença de desempenho?
Eu li alguma outra discussão sobre++i
ei++
(não exaustivamente), mas não encontrou nenhuma resposta específica do Java e diretamente relacionada ao caso em que++i
oui++
está envolvido em uma comparação de valores.