Static x Nova Instância ! Qual tem melhor perfomace?

15 respostas
Jose111

Então como o título do tópico diz, gostaria de discutir qual tem melhor perfomace na seguinte situação:

public class A{

static int atributoStatic;

public static int retornaAtributo(){
  return atributoStatic;
}

}

//em outra classe qualquer
variavel=A.atributoStatic;
A.retornaAtributo();
public class B{

private int atributo;

public int retornaAtributo(){
  return atributo;
}

}

//em outra classe qualquer
B b = new B();
variavel=b.retornaAtributo();

Obs: pseudo-código.

15 Respostas

E

Você está comparando laranjas e maçãs. Se você vai usar programação orientada a objetos, crie uma instância nova ou use um singleton. Se você vai usar programação estruturada (coisa antiga, do tempo dos aviões a hélice) use static.

J

com static você vai manter a variável na ram, então a performance é melhor. Em contrapartida vai consumir mais memória, o que pode fazer seu software ferrar com a máquina.

JavaLivros

Tem alguma forma de usar o mesmo recurso em outra linguagem que não ocorra tal situação comprometedora, usando o static talvez em Groove não sei ?

J

Tem alguma forma de usar o mesmo recurso em outra linguagem que não ocorra tal situação comprometedora, usando o static talvez em Groove não sei ?

Se a linguagem suporta a keyword static, pode sim. É um recurso muito bom, e , pode ferrar a performance do pc se o programador não tiver noção do que faz. Java possui coletor de lixo, e , em variáveis estáticas, o coletor não passa. Então é preciso certos cuidados.

C

Existe “variável” que não fique na RAM?

J

Existe “variável” que não fique na RAM?

Estamos falando do tempo de vida da variável, e isso depende do escopo. A static fica constantemente carregada e não sofre ação do coletor.

J

.

ViniGodoy

Legal Java1. Para deixar seus códigos formatados, use a tag code. Como você é novo, vale a pena ler sobre esse recurso aqui:
http://www.guj.com.br/posts/list/50115.java

Sobre o tópico. Nenhum dos dois irá dar diferença significativa de performance.
Então, desencane com isso. Use a solução mais elegante, que é não usar static.

O static pode ser marginalmente melhor, mas provavelmente, se você tiver um problema, não será aí. Além disso, o static representa uma variável única, enquanto a variável de instância, existirá em cada objeto criado. Para criar um static “por instância”, você acabará criando um map, e isso detonará o ganho de performance que você inicialmente queria ganhar.

J

.

ViniGodoy

Java1:
Mas é claro que fará diferênça.
static não representa variável única. Leia sobre o Singleton que eu escrevi no post anterior.
static em métodos significa apenas “acessível sem criar instância”.

Observe mais as classes que vc usa do JDK; como Calendar, NumberFormat, DateFormat… etc.

Estou dizendo que é extremamente improvável que ele vá ter um problema de performance, e vai resolve-lo usando static. A diferença de tempo nesse caso é mínima, e duvido muito que um profiling algum dia vá acusar isso. Existem centenas de pontos mais prováveis de constituirem gargalos num código comum.

Não entendi o que você quis dizer ao mandar eu ler sobre Singleton. Ali você só cita que o Factory Method não exige a criação de um singleton. O que em absoluto isso tem a ver com a discussão? Eu conheço bem as classes que você citou, e seus construtores estáticos. Assim como posso citar diversas outras (os wrappers de tipos primitivos, como Integer, a classe InetAddress, e de fábricas não estáticas: BufferedImage e Graphics).

Eu apoio o uso de Factory methods por questão de clareza, mas não por preocupações com performance.

ViniGodoy

By the way, estavamos falando que variáveis estáticas são únicas, mas não citamos sobre a possibilidade de métodos estátic criarem objetos não estático. Isso porque o tópico do autor faz menção a um atributo static.

Caso você queira manter um atributo estático é que se aplica as restrições que falei.

ViniGodoy

Aliás, quando falamos do mito de otimizar com final, que tal citar alguns artigos do próprio criador da linguagem?


J

.

peczenyj

A JVM tem otimizador just-in time, a melhoria de performance com static pode ser tão pequena ao longo do tempo que pode não compensar a manutenção no codigo depois (humm… pq isso é static mesmo?).

Como o ViniGodoy falou, basta rodar um profiling e analisar os outros gaps do sistema quando a performance começar a dar problema. Meu medo ao ver esse tipo de topico é BELEZA, STATIC É MAIS RAPIDO, AGORA TUDO É STATIC!!!

Que nem aqueles casos onde o vivente pesquisa e diz “puxa, retornar -1, -2 é mais rapido que lançar uma exception! adeus exception!!!” sem olhar que cada contexto é diferente. Até pq -1 não tem StackTrace.

J

Lá vai:
Há mais motivos para se usar static do que ter ou não performance. Então não estou apoiando o uso de static para performance.

Métodos estáticos e finais são tratados pela JVM como Inline. Sempre que puderem usem static e/ou final (final com algumas considerações).

Um cache interno vai para um estado mono mórfico em primeira convocação, e permanece nesse estado, desde que o tipo de receptor exato (não um subtipo) é repetido a cada momento.
Um cache interno vai para um “megamorphic state” se um segundo tipo de receptor é encontrado.
Chamadas Megamorphic de construção utilizam codificações ocultas vtable e rentáveis, corrigidas em pelo JVM e o compilador não precisará gerenciá-las.
http://wikis.sun.com/display/HotSpotInternals/PerformanceTechniques .

Então, static em métodos não afeta a performance, isso não quer dizer que vamos sair por ai definindo tudo como static.

Além disso; Construtores públicos em Java tornam mais difícil para os desenvolvedores decidirem qual construtor chamar, porque não comunicam intenção.

Por exemplo:

//Vamos ao mais usual, o que eu não gosto de fazer.

persistencia.insert(new NomeObjeto(descricao, grupo));

 

persistencia.update(new NomeObjeto(descricao, grupo)); //Aqui foi usado o construtor errado. Na verdade, nem é costume criar esses construtores, na maioria das vezes usam set depois de usar new.

No exemplo do update o objeto não possui o código necessário usado para atualizar com DAO e esse é um estado para insert!! Imagine quando vc possuir N contrutores, ficará dificil saber qual usar para que uma operação seja bem sucedida. “Quando se deve enviar zero para o código?”, “Quando se deve enviar null para o contrutor?”.

Todo mundo que usa “new MulherObjeto()” sem um método de Criação usa configuradores setAlgumaCoisa() quase uma centena de vezes em um único sistema para configurar esse mesmo objeto. Nisso mora a perda de tempo mascarada.

Car ferrari = new Ferrari();  //Ferrari é uma classe concreta, mas não em sua intenção de código e em sua criação caiu em uso para a abstração, pois apenas é do tipo Ferrari de Car até que seja configurado.

 

//Agora ela vira uma Ferrari concreta recebendo características.

ferrari.setCor(Ferrari.ColorRed);

ferrari.setModel(Ferrari.MODEL_2009);

ferrai.setMaxVelocy(ferrari.testMotor())

ferrari.runWhenPossible();

 

Car ferrari = new Ferrari(Ferrari.COLOR_RED, Ferrari.MODEL_2009);

 

//Como ficaria a Classe Ferrari usando construtor com fields. 

public Ferrari (int color, int model) {

  this.setColor(color);

  this.setModel(model);

  this.setMaxVelocy(testMotor());

}

Então algum desavisado faria assim: Car ferrari = new Ferrari().runWhenPossible(); //vai dar merda , PORQUE o carro não foi configurado como deveria…

Problemas:

Toda vez que uma Ferrari for criada, ela terá que ser configurada; e por quem não entende nada de Ferrari. ;).

Redundância de código.

Dá muitas possibilidades de criação, o que não é bom para um carro; por exemplo: a velocidade máxima pode ser configurada com 10km, o modelo pode receber uma cor que não existe para aquele ano, e certamente será necessária a criação de uma regra que lançará uma exceção quando alguém configurar errado. Para quem adora complexidades e exceções isso pode parecer mais eficiente com os prazos; mas não para mim!

//Agora vamos a mais performática, fácil, mais rápida para desenvolvimento, mais coesa, mais tudo…

Ferrari.getModel2009Red().runWhenPossible(); //Not problem, it's OK!

 

//Como ficaria a Classe Ferrari.

private Ferrari (fint color, final int model) {

  this.color = color;

  this.model = model;

  this.maxVelocy = testMotor());

}

 

public static Ferrari getModel2009Red() { //Resume a intenção de obter um Model Red 2009, economiza TEMPO no desenvolvimento.

   return new Ferrari(Ferrari.COLOR_RED, Ferrari.MODEL_2009, ... mais);

}

//sem métodos configuradores para setColor(), setModel(), setMaxVelocy(), o que reduz e muito o acoplamento, entre outros.

O JVM pode ainda compilar NATIVAMENTE por causa da quantidade de chamadas, não precisará gerenciar, e no nome do método será expresso a intenção de negócio.

Um erro comum é afirmar que métodos de Factory só podem ser aplicados com Singleton, ou são Singleton. Isso é um engano. O padrão que eu descrevi acima pode ser chamado de: “Static Factory Method”, ou simplesmente: Método de Criação. Isso porque ainda não fornece acoplamento fraco como um Factory Method genuíno ou Abstract para famílias de objetos relacionados.

Agora vamos falar do uso modificador final, com intenção de desempenho.

“é exagero”, “é lenda urbana”, “é otimização prematura” um dos principais evangelistas da Sun Brian Goetz afirma! http://www.ibm.com/developerworks/java/library/j-jtp1029.html

Mas será que ele levou em consideração a documentação da Sun?

Lá vai:

At run time, a machine-code generator or optimizer can “inline” the body of a final method, replacing an invocation of the method with the code in its body. Ou seja, a chamada do método é substituída pelo corpo ou retorno do método. http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html no índice 8.4.3.3.

Tudo bem, concordo que é um exagero, otimização prematura, mas não é lenda, é oficial da Sun:

In the past, programmers often inserted the “final” keyword for exactly this reason. Or to better facilitate inlining and increase execution speed, they would combine many smaller methods into one larger method. But in many ways, such techniques defeat the entire facility of modularization and reusability built into the programming language.
Unlike traditional virtual machines, the Java HotSpot VM is able to inline the class without the “final” keyword: http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html

Conclusões: Diretamente do departamento de obscuridade do Fábio, tirem as suas conclusões.

James Gosling é o criador do Java, Brian é Evangelista.

Abraços,

Fábio Henrique.


Novo Internet Explorer 8: traduza com apenas um clique. Baixe agora, é grátis!

Criado 14 de setembro de 2009
Ultima resposta 11 de out. de 2009
Respostas 15
Participantes 8