Otimização de código.  XML
Índice dos Fóruns » Java Básico
Autor Mensagem
Paulo Silveira
Administrador
[Avatar]

Membro desde: 07/08/2002 18:38:50
Mensagens: 4204
Localização: São Paulo
Offline

renrutal wrote:
Paulo Silveira wrote:Mesmo assim, ainda nao deve ser usado para concatenar dentro de um laco se a string que voce esta mexendo esta referenciada fora do laco! Ele geraria milhares de StringBuilders, estressando o GC. Fica uma carroca


Aí não tem versão de Java que resolva né? É problema de estrutura de código, não da linguagem.


Perfeito, isso mesmo.

http://blog.caelum.com.br twitter: @paulo_caelum


[Email] [WWW]
Foxlol
Virtual Machine Man
[Avatar]

Membro desde: 02/05/2006 10:17:47
Mensagens: 646
Localização: São José do Rio Pardo - SP
Offline

Peraee!!!

Dexa eu ver se eu entendi ou to boiando.

Quer dizer que depois do Java 6, ao usar "+" para concatenar String, o compilador substitui automaticamente para StringBuilder?

O.o

Sun Certified Java Programmer
Sun Certified Web Component Developer
Java EE 5 Business Component Developer Oracle Certified Professional
[MSN] [ICQ]
Paulo Silveira
Administrador
[Avatar]

Membro desde: 07/08/2002 18:38:50
Mensagens: 4204
Localização: São Paulo
Offline

Foxlol wrote:Peraee!!!

Dexa eu ver se eu entendi ou to boiando.

Quer dizer que depois do Java 6, ao usar "+" para concatenar String, o compilador substitui automaticamente para StringBuilder?

O.o


Desde o Java 1.0 é usando o StringBuffer.

O problema é que a primeira vez ele da new em String Buffer. Se estiver dentro de um loop, ja viu... Qual eh a solucao? Dar new FORA do laco, e dentro so chamar append. Mas isso ai o compilador nao faz.

http://blog.caelum.com.br twitter: @paulo_caelum


[Email] [WWW]
Foxlol
Virtual Machine Man
[Avatar]

Membro desde: 02/05/2006 10:17:47
Mensagens: 646
Localização: São José do Rio Pardo - SP
Offline

Paulo Silveira wrote:
Foxlol wrote:Peraee!!!

Dexa eu ver se eu entendi ou to boiando.

Quer dizer que depois do Java 6, ao usar "+" para concatenar String, o compilador substitui automaticamente para StringBuilder?

O.o


Desde o Java 1.0 é usando o StringBuffer.

O problema é que a primeira vez ele da new em String Buffer. Se estiver dentro de um loop, ja viu... Qual eh a solucao? Dar new FORA do laco, e dentro so chamar append. Mas isso ai o compilador nao faz.


Eita, não sabia dessa!

Então dá pra concatenar Strings com "+" sem problemas, desde que não esteja em um loop. Ai tem que tomar este cuidade que vc falou.

Vlw

Sun Certified Java Programmer
Sun Certified Web Component Developer
Java EE 5 Business Component Developer Oracle Certified Professional
[MSN] [ICQ]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20581
Localização: Curitiba/PR
Offline

sergiotaborda wrote:
ViniGodoy wrote:
No caso do equals, nessa situação específica, você vai ter um processo lijeiramente mais longo, pois serão feitas três comparações. A primeira, testa se a string passada no parâmetro é a própria instância (o que nunca vai ocorrer). A segunda, testa se o objeto passado por parâmetro é realmente um String (o que sempre vai ser). E a terceira, finalmente, testa se o tamanho das Strings bate (o que só será verdade para um string vazio).

Não. "abc" e "def" têm o mesmo length. Só se o tamanho é igual é que se tem que passar a uma analise caracter a caracter. Os outros testes são otimizações. O segundo teste tb teste o null. Nem sempre vai ser uma string


Sérgio, estou falando do teste:


Que foi proposto pela Lina, no início do tópico. Não tem absolutamente nada a ver com coleções.

E, como mostrado no código fonte da classe String (está no início do tópico), são feitas 3 comparações, sendo 2 delas desnecessárias.

A primeira, verifica se o objeto recebido no parâmetro e o this são exatamente o mesmo objeto. No caso desse exemplo, as chances disso ocorrer são ridiculamente pequenas.

O segundo teste, verifica se o objeto recebido é realmente uma String. Da forma como a Lina usa isso sempre vai ser verdade. "" nunca será nulo e sempre será uma String. Não estou criticando o mérito desse teste, no caso de um método equals de verdade, ele é necessário. Mas o que ela quer não é testar igualdade, mas se um determinado String está vazio ou não.

Só então, é feito um cast, uma atribuição a uma variável "n" e uma comparação em para só então ocorrer a comparação com o tamanho, que você falou. Por favor, leia o tópico com mais atenção da próxima vez. Aliás, em momento algum falei sobre ser mais lento por haver comparação caracter a caracter.

A forma que eu recomendei foi o simples de tamanho == 0. Essa forma é, sim, mais rápida, já que poupa os dois testes iniciais que só são necessários e servem de otimização no caso do equals.

Mas, como eu ressaltei e volto a ressaltar, não adianta otimizar código se você não estiver num ponto que constitui um gargalo em sua aplicação.

This message was edited 2 times. Last update was at 30/04/2008 09:16:40


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
Bruno Laturner
GUJ Expert
[Avatar]

Membro desde: 18/02/2008 16:17:53
Mensagens: 3002
Offline



100 milhões de iterações, em milissegundos:



Edit 2: Corrigido o benchmark
Edit 3: Refatorado o benchmark

This message was edited 3 times. Last update was at 30/04/2008 10:30:52


A resposta acima foi achada em menos de 5 minutos no google.
The prisoner falls in love with his chains. --E.W. Dijkstra
[WWW]
Bruno Laturner
GUJ Expert
[Avatar]

Membro desde: 18/02/2008 16:17:53
Mensagens: 3002
Offline

Editei o post acima.

This message was edited 1 time. Last update was at 30/04/2008 10:23:23


A resposta acima foi achada em menos de 5 minutos no google.
The prisoner falls in love with his chains. --E.W. Dijkstra
[WWW]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20581
Localização: Curitiba/PR
Offline

Tem algo errado nesse seu benchmark.

Veja só, o método isEmpty está implementado assim:
return count == 0;

Isso é exatamente o que faz o seu teste com length.
Alguém saberia explicar pq ele tem a mesma performance do equals?

De qualquer forma, ele vem a provar que a performance desses métodos é tão boa, que dificilmente eles ocasionariam problemas de performance para essa situação.

This message was edited 2 times. Last update was at 30/04/2008 10:18:17


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
thegoergen
Virtual Machine Man
[Avatar]

Membro desde: 24/09/2007 09:44:03
Mensagens: 583
Localização: Estrela/RS
Offline

Erro na linha 16!



Você está chamando o método testeEquals2 e não o testeIsEmpty...

"A preguiça de pensar é a maior burrice de uma pessoa." (Diego Inácio Goergen)

CV: Diego Inácio Goergen

Administrador da UNISCWiki e Medicina UNISC
[WWW] [MSN] [ICQ]
Bruno Laturner
GUJ Expert
[Avatar]

Membro desde: 18/02/2008 16:17:53
Mensagens: 3002
Offline

Corrigi o benchmark. Agora ele faz só médias.

A resposta acima foi achada em menos de 5 minutos no google.
The prisoner falls in love with his chains. --E.W. Dijkstra
[WWW]
sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline

ViniGodoy wrote:
sergiotaborda wrote:
ViniGodoy wrote:
No caso do equals, nessa situação específica, você vai ter um processo lijeiramente mais longo, pois serão feitas três comparações. A primeira, testa se a string passada no parâmetro é a própria instância (o que nunca vai ocorrer). A segunda, testa se o objeto passado por parâmetro é realmente um String (o que sempre vai ser). E a terceira, finalmente, testa se o tamanho das Strings bate (o que só será verdade para um string vazio).

Não. "abc" e "def" têm o mesmo length. Só se o tamanho é igual é que se tem que passar a uma analise caracter a caracter. Os outros testes são otimizações. O segundo teste tb teste o null. Nem sempre vai ser uma string


Sérgio, estou falando do teste:


Que foi proposto pela Lina, no início do tópico. Não tem absolutamente nada a ver com coleções.

E, como mostrado no código fonte da classe String (está no início do tópico), são feitas 3 comparações, sendo 2 delas desnecessárias.

A primeira, verifica se o objeto recebido no parâmetro e o this são exatamente o mesmo objeto. No caso desse exemplo, as chances disso ocorrer são ridiculamente pequenas.


Sim. Mas vc escreveu "o que nunca vai ocorrer" lol
Agora eu entendi que vc estava falando do caso especifico de string.equals(""). Peço desculpas se o ofendi.


Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
thegoergen
Virtual Machine Man
[Avatar]

Membro desde: 24/09/2007 09:44:03
Mensagens: 583
Localização: Estrela/RS
Offline

Interessante... o


Demora mais que o


Por que isso??

"A preguiça de pensar é a maior burrice de uma pessoa." (Diego Inácio Goergen)

CV: Diego Inácio Goergen

Administrador da UNISCWiki e Medicina UNISC
[WWW] [MSN] [ICQ]
pgioseffi
JavaChild
[Avatar]

Membro desde: 21/03/2011 09:10:57
Mensagens: 130
Localização: Rio de Janeiro, RJ
Offline

Foxlol wrote:Com a primeira opção vc estará criando uma String a mais na memória.
Já com a segunda é apenas uma comparação com um tipo primitivo.


Foxlol,

Conforme sugere o método java.lang.String#intern(), acredito que no caso específico da String "", ela já esteja na memória através do pool de Strings mantido pela própria classe, não onerando assim a memória ao instanciar mais um objeto.

Atenciosamente,
Philippe Gioseffi
[Yahoo!] aim icon [MSN]
pgioseffi
JavaChild
[Avatar]

Membro desde: 21/03/2011 09:10:57
Mensagens: 130
Localização: Rio de Janeiro, RJ
Offline

ViniGodoy wrote:O length é mais rápido por se tratar apenas da leitura de um atributo e da comparação no seu if, observe (esses códigos foram retirados da classe String):


No caso do equals, nessa situação específica, você vai ter um processo lijeiramente mais longo, pois serão feitas três comparações. A primeira, testa se a string passada no parâmetro é a própria instância (o que nunca vai ocorrer). A segunda, testa se o objeto passado por parâmetro é realmente um String (o que sempre vai ser). E a terceira, finalmente, testa se o tamanho das Strings bate (o que só será verdade para um string vazio).



Usando o equals é ainda mais recomendado colocar a constante na frente, assim:


Isso dá uma vantagem adicional, pois o código também falha caso a string seja nula. Nos seus exemplos, você acabaria com um NullPointerException.

Agora, não creio que isso seja otimização de código, a menos que você esteja num loop realmente intenso, comparando milhares de Strings por segundo. Provavelmente haverá outros locais muito piores na sua aplicação. Não adianta "otimizar" pontos fora desses gargalos. Você só aumentará o tempo ocioso do sistema, que espera o gargalo passar. Sempre que se falar em otimização, rode um profiler, como o do Netbeans, e identifique os pontos de baixa performance. Otimize apenas esses pontos.

Otimização tem um custo: ela torna o código mais complexo e muito menos flexível. E deve ser uma preocupação apenas nos momentos de projeto e nos pontos críticos identificados no código.


ViniGodoy,

Conforme falei acima, se vc olhar o javadoc do método java.lang.String#intern(), a primeira comparação se faz necessária, pois o objeto pode estar no pool de Strings mantido pela própria classe.

Quanto a vc afirmar que a segunda comparação tbm será sempre verdadeira, tbm discordo... O método equals espera um Object, então qualquer coisa pode ser passada e em um projeto com muitos estagiários você pode ver a invocação do método equals de uma String recebendo como parâmetro um Double, por exemplo.

Já a terceira comparação não entendi pq vc afirmou ser possível somente para String vazia.

Atenciosamente,
Philippe Gioseffi
[Yahoo!] aim icon [MSN]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20581
Localização: Curitiba/PR
Offline

Observe que falei que é "nessa situação específica". Ele estava querendo testar se uma string era vazia através da comparação "".equals(string) - Aliás, isso também é explicado para o sergio taborda bem no início do post onde vc fez quote.

No caso dessa comparação é muitíssimo raro que a string recebida seja igual idêntica a String vazia (passe no ==). O método intern pode garantir isso, mas ele também exige custo computacional, e muito maior que o do equals. Como ele também disse que passaria uma string por parâmetro, sabíamos que não se tratava de outra classe.

É por isso mesmo que o método equals é mais lento que o length para testar String vazia. Por que ele:
a) Se previne contra o uso incorreto (já que pode receber um object);
b) Testa se os objetos são idênticos (o que normalmente não vai ocorrer).

No caso, o length não precisa fazer nada disso.


Em todo caso, desde o Java 6, essa dúvida já não existe mais. Inseriram o método isEmpty() na classe String. Por isso que não é muito saudável ressuscitar discussões de 2008. E, lógico, sua implementação baseia-se no length().


Não estou falando que a implementação do equals é errada. Na verdade, esses fatores são otimizações para quando se quer testar se duas strings são iguais. Porém, isso não quer dizer que elas sejam eficientes para testar o vazio. E, como eu já disse outras vezes no tópico, a diferença de 1 if para 3 ifs em termos de performance é apenas acadêmica pois, na prática, dificilmente isso aí constituirá um gargalo de performance em qualquer aplicação comercial.

This message was edited 3 times. Last update was at 24/05/2011 13:18:06


@ViniGodoy - Lattes

Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!

Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).

Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295
[WWW]
 
Índice dos Fóruns » Java Básico
Ir para:   
Powered by JForum 2.1.8 © JForum Team