Declaração dentro de loops

20 respostas
danieldestro

Pessoal, tenho uma dúvida trivial.

Isto:

... int i = 0; while( x < 1000 ) { i = y + z; x = i * 10; } ...

é diferente disto?

... while( x < 1000 ) { int i = 0; i = y + z; x = i * 10; } ...

Não quero dizer sobre o escopo de i, mas sim sobre performance, alocação de memória e etc.

20 Respostas

N

A diferença é que no primeiro não precisa alocar a variável i toda vez no loop, pois ela já foi alocada; mas na segunda toda vez que entrar no loop ele tem alocar memória para variável i, então vc tem uma perda de performance. Se estiver errado, me falem !!!

Luca

Olá

Os 2 modos mostram erros de programação criando um loop eterno, a variável x JAMAIS será maior do que 1000. Pode até compilar corretamente.

E mais, não faz sentido nenhum reinicializar a variável i = y + z em todas iterações pois ela depende de grandezas y e z que não variam dentro do loop. A regra é tirar do loop tudo que não varia.

[]s
Luca

danieldestro

Amigo Luca, você não pegou o espírito da coisa.

Luca

Olá

Certo, concordo que radicalizei. Mas seu exemplo podia ser mais caprichado. Como está o x não varia pois é soma de 2 coisas que não variam.

Mas de todo modo respondi quando disse que dentro do loop não devem ser colocadas coisas que não variam.

[]s
Luca

danieldestro

Eu mencionei, no título do POST sobre DECLARAÇÃO
Mas, para te satisfazer, Luca.

Este código:

... int i = 0; while( x < 1000 ) { //... } ...

é diferente disto?

... while( x < 1000 ) { int i = 0; //... } ...

Não quero dizer sobre o escopo de i, mas sim sobre performance, alocação de memória e etc.

Luca

Olá

Agora sim!!!

Esta questão depende da otimização que o compilador faz com seu código. A menos que você compile com opção de compatibilidade com uma JVM muito antiga, geralmente o próprio compilador percebe a inutilidade de fazer int i = 0 dentro do loop e retira dos bytecodes finais (se não há necessidade por questões de escopo). Mas bem que a gente pode dar uma ajudinha ao compilador e já programar mais bonitinho.

[]s
Luca

danieldestro

Neste caso a gente tem um ponto.

Não preciso me lembra de iniciar a variável com algum valor, toda vez que o loop itera.

int i = 0; while (true) { i = 0; //... i = recebeUmValorImportante( ); }

cv1

O compilador se vira bem, entao nao vejo motivos pra isso, uma vez que ajudar o compilador geralmente nao ajuda o pobre coitado que esta tentando decifrar o teu codigo :smiley:

Mas, Daniel, se vc quiser ter CERTEZA ABSOLUTA do que esta acontecendo com o seu codigo, aprenda a ler a saida do “javap -c” - ele te da um disassemble dos bytecodes de uma classe ou metodo qualquer, e assim vc pode ver direitinho se faz alguma diferenca. Provavelmente, nesse caso, nenhuma, mas nunca se sabe :slight_smile:

E

É bem melhor ajudar você ou quem vai ler o seu código do que ficar se preocupando com a otimização. Só otimize algo se realmente a diferença de desempenho for muito grande, do contrário é perda de tempo e o código acaba ficando “feio”.
Livros sobre XP e Refactoring ajudam muito :slight_smile:

danieldestro

EddiE, você é muito feio!

Valeu povão!

E

obrigado :stuck_out_tongue:

vale muito o significado da expressão… :wink:

louds

“Luca”:
Olá

Agora sim!!!

Esta questão depende da otimização que o compilador faz com seu código. A menos que você compile com opção de compatibilidade com uma JVM muito antiga, geralmente o próprio compilador percebe a inutilidade de fazer int i = 0 dentro do loop e retira dos bytecodes finais (se não há necessidade por questões de escopo). Mas bem que a gente pode dar uma ajudinha ao compilador e já programar mais bonitinho.

[]s
Luca

Negativo, segundo a JLS esse tipo de otimização não é válida.
Compilador java algum faz qualquer tipo de otimização no código; somente os os jitters realizam alguma.

Existe um erro de conceito quando se fala em alocação das variaveis locais no java para a maioria das pessoas.

O custo de voce ter uma variavel local é irrisorio, em termos de uso de cpu (ignorando o gc por agora), é constante quanto ao número delas. Sim, isso mesmo, ter 1, 2 ou 100 variaveis locais vai consumir a mesma quantidade de ciclos da sua cpu.

Quanto a memoria utilizada, a conta não é trivial. O espaço total utilizado é igual ao máximo de variaveis visiveis para um statement do seu método. No exemplo do Daniel o uso é identico.

Mas qual método é mais rápido? O primeiro, por que o segundo faz um armazenamento morto (dead store, exite termo melhor?) em i “int i = 0”.

re-escrevendo o código assim:

while( x < 1000 ) {
  int i = y + z;
  x = i * 10;
}

A performance vai ser identica dado que ambos vão gerar exatamente o mesmo bytecode para o loop.

Ai vão algumas dicas de micro-optimização para java:

-Evite branches ao máximo, se não for possivel faça que o caso commum seja de branches pra traz aceitos e para frente rejeitados.

-Alinhe os dados da sua classe em 16 bytes levamos em conta os headers do objeto, 8 bytes na JVM da Sun.

-Selecione corretamente os operadores matematicos, adição sobre shifts, shifts sobre multiplicação.

-Não utilize valores ponto flutuante desnormalizados.

-Para estruturas vetoriais, utilize um vetor de arrays em vez de um array de vetores.

Luca

Olá

Perfeita a observação do Louds sobre os jitters. O compilador Java não é um compilador como todos entendemos e até estudamos. Não é como o C que gera um objeto já otimizado com as opções especificadas. Aliás javac nem mesmo possue opções de otimização.

E também está certo quando diz que o trabalho maior ou menor do compilador não tem nada a ver com o que vai acontecer na execução do aplicativo. Este tipo de conhecimento é mais fácil para quem já programou em C (e assembler) e conhece como a memória é mapeada e paginada nos computadores modernos.

Um código bonitinho e sem declarações redundantes é bem mais fácil de ler. Alías padronizar e embelezar o código com ferramentas do tipo JBeauty é comum em muitos ambientes de desenvolvimento justamente para facilitar a leitura e manutenção.

Entendi o que o CV pensou quando disse que facilitar a vida do compilador pode levar a códigos ilegíveis. Mas o que se passava na minha cabeça era somente o uso de boas práticas tais como muitos autores recomendam.

[]s
Luca

Ironlynx

O custo de voce ter uma variavel local é irrisorio, em termos de uso de cpu (ignorando o gc por agora), é constante quanto ao número delas. Sim, isso mesmo, ter 1, 2 ou 100 variaveis locais vai consumir a mesma quantidade de ciclos da sua cpu.

Sim eh irrisório,mas deve-se levar em conta q ela é alocada na Stack,q se não me engano,tem só 220Kbytes(tah certo q isso é coisa pra kct p/variáveis locais),fora o fato de não se preocupar com o gc;pois varíáveis com escopo de método,e q não forem passadas a objetos,jamais serão alocadas na Heap,e somentes atributos alocados na Heap são coletados pelo Coletor de Lixo,pois os demais são perdidos ao término dos limites do seu uso(ESCOPO).O espaço total = Heap+Stack;Só se faz necessário abrir o olho para as variáveis(na Stack) se o seu código for gerar muitas variáveis novas(caso de programas q fazem uso de recursividade),pois o estouro pode ocorrer…(na verdade é provável q ocorra)

louds

Esse tamanho é ajustavel com o parametro -Xss. O tamanho inicial eu desconheço.


(tah certo q isso é coisa pra kct p/variáveis locais),fora o fato de não se preocupar com o gc;pois varíáveis com escopo de método,e q não forem passadas a objetos,jamais serão alocadas na Heap,e somentes atributos alocados na Heap são coletados pelo Coletor de Lixo,pois os demais são perdidos ao término dos limites do seu uso(ESCOPO).O espaço total = Heap+Stack;Só se faz necessário abrir o olho para as variáveis(na Stack) se o seu código for gerar muitas variáveis novas(caso de programas q fazem uso de recursividade),pois o estouro pode ocorrer…(na verdade é provável q ocorra)

Usar recursividade em linguagens imperativas é um erro.

Hmm, veja bem, a pilha guarda uma enorme variedade de coisas, não somente as variaveis locais:

-call frames
-variaveis temporarias para cálculo
-parametros das funções
-exception frames

Meu ponto é que usar variaveis locais é ordens de magnitude mais rápido que objetos, como o luca mesmo falou, sem entender de asm é dificil saber oque realmente acontece…

Ironlynx

Esse tamanho é ajustavel com o parametro -Xss. O tamanho inicial eu desconheço.

O stack size inicial é 220kBytes.mudar o tamanho(completando o louds):
java -Xss:tamanho NomeDoPrograma //para quem não sabe

Para isso existe Haskell :smiley:
Agora,vai dizer isso para os professores.Ah e java é mais do que linguagem imperativa.(Mas tb o é) :wink:

Sim,mas a grosso modo podemos dizer q a Stack é utilizada para tudo q vai existir(ter vida somente-exceto objetos) dentro de um método.Var locais e parametros paras funções são os mais comuns…

Com certeza,não há nem o q discutir…o SP(e tudo q ele aponta) só é mais lento do que os registradores,algo q programador Java algum tem acesso(ou seus programas).

louds

De onde voce tirou essa informação? Tou absurdamente curioso! A documentação do JDK não fala qual o tamanho padrão da pilha, o fonte da JVM a grossos olhos não tem um tamanho default que não seja o do SO.

Hmmm, é? Nunca realizei este fato.

dreamspeaker

Fiquei com dor de cabeça de ler esse tópico… :shock:

N

Eu não li para não dar dor de cabeça !!!

Ironlynx

louds,dias atrás,fui fazer um tutorial sobre passagens de parâmetro em java(eu tava pesquisando sobre stack e heap),e descobri esse link:
http://www.ime.usp.br/~peas/monitoria/mac122.html

Um tal paulo silveira diz q o stack size por default é 220kbytes…acho q ele é uma fonte confiável né?Mas de onde ele tirou isso eu não sei!E tb tô super curioso para saber!(Rodei a Sun toda atrás dessa info,mas acho q ele pagou um cafezinho pro gosling revelar detalhes da JVM…)Ah,vc tah certo,a documentação não tem nada a respeito! :?

Nota:O tam da heap inicial é fácil de saber pois é calculado baseado na memoría física da máquina e o algoritmo q a aloca tenta fazer o uso o máximo possível desta memória.(Na verdade,ele tenta usar metade da memória disponível,mas se a memória for inferior a 160mb ele tenta usar o máximo q puder)

Criado 7 de janeiro de 2004
Ultima resposta 8 de jan. de 2004
Respostas 20
Participantes 8