Metodo System.gc();

54 respostas
N

[i]Pessoal com o uso do metodo System.gc(); que elimina objetos não usadoos! Quanto a isso gostaria de saber!

  • isso traz ottimização ao codigooo?

  • quando é usado ?

  • á exemplo de algum codigo ?

  • Garbage Collector = " Coletor de Lixo Java ".

// ATT ();[/i]

54 Respostas

F

Não use System.gc()

O Garbage Collector funciona normalmente sem a interferencia dos desenvolvedores, se estive com algum problem é sua aplicação que está com um gargalo que deve ser tampado

[]'s

B

Favor usar uma fonte normal de texto…

  1. Não traz otimização, aliás é melhor evitá-lo. A JVM que sabe a melhor hora de fazer coleta de lixo
  2. Um caso que conheço de uso é quando você quer apagar um arquivo, e a JVM fala que o arquivo ainda está em uso pelo sistema, mesmo que não esteja. Um jeito de contornar é usar o System.gc() antes do file.delete(). Melhor mesmo seria fazer isso numa nova tentativa de apagar o arquivo.
  3. Exemplo não tenho, é só usar.
V

Realmente, como os colegas falaram, não traz otimização.

Repare também que a documentação do método diz que a VM não é obrigada a executar o garbage collector assim que o comando é chamado. Esse comando é só uma sugestão.

Esse comando é útil em algumas situações, geralmente muito específicas. Por exemplo, entre uma fase e outra de um jogo, ou antes de exibir um vídeo. Assim você reduz as chances de haver uma coleção de lixo longa no meio da sua tarefa principal. Para aplicações comerciais no geral, não vejo nenhum motivo para usa-lo.

N

Onde eu encontro a documentação dos metodos?

OBG.

J

Pode usar sim. Usando esse método você estará forçando a coleta de lixo. Em algumas aplicações, pode-se ganhar performance, se puder evitar o acumulo de objetos na memória. O gc pode demorar alguns segundos realizando trabalho em grandes coletas.

exemplo:

método que lê imagens de um stream de video e as filtra.

private doErosion(BufferedImage bi){

 int width = 100;
 int height = 100;
    
BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
bimage = Filter.Erosion(bi);
 
bi = Filter.Clone(bimage);
bimage = null; //passando null para bimage, faz com que o coletor de lixo passe a enxerga-la. É útil também em aplicações que usam muitos String;
System.GC(); // realiza a coleta de lixo.
}

Agora não compensa usar, se, a sua aplicação não requer tempo crítico de processamento. É melhor a máquina virtual realizar automaticamente.

Esse link pode ser útil:

http://www.roseindia.net/javatutorials/determining_memory_usage_in_java.shtml

B

Documentação:

http://java.sun.com/javase/6/docs/api/index.html?java/lang/System.html#gc()

V

Só reiterando, você não está forçando, está apenas sugerindo. É muito raro a VM ignorar o comando (pelo menos a da sun).

J

Só reiterando, você não está forçando, está apenas sugerindo. É muito raro a VM ignorar o comando (pelo menos a da sun).
A vm pode ignorar o comando?

J

É verdade. Não havia lido corretamente a documentação. Mas é meio estranho sugerir, não!? As vezes, nós precisamos.

V

Só reiterando, você não está forçando, está apenas sugerindo. É muito raro a VM ignorar o comando (pelo menos a da sun).
A vm pode ignorar o comando?

Pode sim. Pelo menos é o que diz a documentação.
Nunca vi isso ocorrer.

Ah, fui dar uma olhada no artigo que você falou, mas ele me pareceu meio antigo (2001). Será que o que está lá ainda vale? O garbage collector é um dos códigos onde a sun dedica maior parte da sua atenção.

M

Sim.

System.GC() não invoca o método que coleta o lixo, ele simplesmente sugere a JVM que aquela é uma boa hora para fazer essa coleta por que tem lixo a ser coletado e provavelmente mais pra frente isso pode ficar pesado.

Mas nada garante que será invocado.

B

Como o ViniGodoy disse, não há nenhuma garantia. Ou mais especificamente, não há garantias que ela vá rodar na hora que foi chamada.

Ela pode ignorar o comando se há uns microsegundos atrás ela já fez o GC Full. Não tem por que rodar duas vezes seguidas.

V

Estranhíssimo. Mas a sun nunca abriu mão do direito único e exclusivo que a VM tem de controlar o gc.
Já foram feitos pedidos para criar comandos que suspendam o gc, ou que forcem sua execução, mas implementações disso sempre foram negadas.

A próxima versão de garbage collector vai trazer modificações importantes, que a princípio o tornará apto a aplicações de tempo real. Mesmo nessa versão, será impossível forçar o gc a fazer qualquer coisa. Se quiser ler mais sobre ela:
http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-5419&yr=2008&track=javase

V

Me enganei, o link que você vai gostar de ver é esse aqui:
http://research.sun.com/jtech/pubs/04-g1-paper-ismm.pdf

J

Estranhíssimo. Mas a sun nunca abriu mão do direito único e exclusivo que a VM tem de controlar o gc.
Já foram feitos pedidos para criar comandos que suspendam o gc, ou que forcem sua execução, mas implementações disso sempre foram negadas.

A próxima versão de garbage collector vai trazer modificações importantes, que a princípio o tornará apto a aplicações de tempo real. Mesmo nessa versão, será impossível forçar o gc a fazer qualquer coisa. Se quiser ler mais sobre ela:
http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-5419&yr=2008&track=javase

Tenho uma aplicação de vídeo, que captura de cameras ip. Isso lendo um mjpeg e criando sequencias jpg. Dado alguns minutos, o gc passava, e a captura parava por uns 10s. Passei a utilizar o System.GC(), e ele passou a realizar a coleta antes do acumulo. Fiz com base naquele artigo que postei. Até hoje não me trouxe mais problemas.

V

Eu tive os mesmos problemas com jogos. Ao final de uma fase, geralmente todos os objetos do cenário são destruídos e um novo cenário é montado.
Então, o usuário começa a jogar a segunda fase e, bem no meio, o jogo congelava. Também resolvi chamando System.gc() logo após a troca de cenário.

J

O G1, que é o novo gc, pelo que li, no link que o vini postou, é capaz de prever o tempo da pausa, e otimizar a coleta. Muito interessante. Vai resolver muitos problemas de performance.

J

Mesmo com o g1, não é garantida a performance, como java realtime system.

V

Sem que o programador controle exatamente o garbage collector, nunca será possível garantir hard-real time.
Pelo menos, não se o intervalo de tempo for muito curto.

S

Estranhíssimo. Mas a sun nunca abriu mão do direito único e exclusivo que a VM tem de controlar o gc.
Já foram feitos pedidos para criar comandos que suspendam o gc, ou que forcem sua execução, mas implementações disso sempre foram negadas.

Não é estranho, aliás é de esperar e totalmente óbvio se você pensar na razão de ter um CG para começo de conversa: ambiente gerenciado.

Ora se o ambiente é gerenciado, em particular a memória, deixar que o programador interfira com isso é totalmente contra o objetivo pois tornaria a VM um ambiente não-gerenciado. O fato de poder sugerir já é muito bom, embora se vc esquecer que isso existe nunca terá problemas.

Se tiver problemas de memoria com java o problema está na sua aplicação , nas API que usa ou na pouca memoria ram disponivel.
mandar o GC correr, não vai alterar a qualidade destas 3 coisas…

O que é estranho é o método gc existir, e não que a sua implementação seja opcional (lembrar que o java é uma especificação).

B

Em teoria, num ambiente gerenciado perfeito, o GC coletaria o lixo na hora certa, usando tempo de processamento mínimo, mantendo a aplicação sempre eficiente. Bem, não vivemos em sonhos.

System.gc() existe por pragmatismo.

J

o grande problema é que o gc não é inteligente, como postado no link anteriormente. http://developers.sun.com/learning/javaoneonline/j...n=TS-5419&yr=2008&track=javase

Se a sun permitisse o controle dele, pelo desenvolvedor, estaria aumentando o poder do java.

V

sergiotaborda:
Se tiver problemas de memoria com java o problema está na sua aplicação , nas API que usa ou na pouca memoria ram disponivel.
mandar o GC correr, não vai alterar a qualidade destas 3 coisas…

Ninguém falou em rodar o gc por problemas de falta de memória. O problema é o gc rodar em horas impróprias, como os casos que citamos acima.

Não acho estranho que esse método exista. Aliás, também acho que deveria ser obrigatória a execução do gc(). Isso não torna o ambiente não gerenciado, de forma alguma. Ninguém está falando aqui em não ter um garbage collector, ou deletar objetos diretamente.

S

juliocbq:
o grande problema é que o gc não é inteligente, como postado no link anteriormente. http://developers.sun.com/learning/javaoneonline/j...n=TS-5419&yr=2008&track=javase

Se a sun permitisse o controle dele, pelo desenvolvedor, estaria aumentando o poder do java.

Vc está assumindo que 1 desenvolvedor é mais oportuno que um algoritmo desenvolvido e comprovando por
dezenas (senão centenas, quiça milhares ) de desenvolvedores. Isso simplesmente não é verdade.

O poder do CG , como do hotspot, está em exactamente ninguem poder por a mão.
Veja, se existisse uma api de controle do CG ninguem poderia lançar um CG que não fosse compativel com ela.
se ela desse muito poder ao programador, nunca teriamos um CG apto para realtime.

A Sun, nem o JCP devem primitir este tipo de promiscuidade. Nunca!

S

ViniGodoy:

Não acho estranho que esse método exista. Aliás, também acho que deveria ser obrigatória a execução do gc(). Isso não torna o ambiente não gerenciado, de forma alguma. Ninguém está falando aqui em não ter um garbage collector, ou deletar objetos diretamente.

Mas indirectamente estão dizendo que querem controlar quando ( e possivelmente como) o CG roda. Isso é mesmo que o CG
não ser mais independente da aplicação.

Veja,Iterator.remove tem implementação opcional. Isto significa que vc pode mandar deletar e não vai acontecer. Inesperado talvez
mas a especificação tem que ser assim para dar conta de Arrays.asList().iterator().remove() que não pode remover os itens já que o proxy é imutável. O mesmo acontece com o CG. Porque ele é isolado e vc não o pode comandar (pode sugerir, não comandar) ele tem muita mais flexibilidade. É quase que o principio de hollywood (“don’t call us, we will call you”) so que “don’t call us, we know what to do better than you”. O CG precisa ser isolado (ou seja, náo pode existir forma de o comandar)

G

Desculpem interromper a discussão*, mas esse link tá quebrado… alguém sabe se tem um outro que funcione?

  • Muito interessante por sinal.
J

Desculpem interromper a discussão*, mas esse link tá quebrado… alguém sabe se tem um outro que funcione?

  • Muito interessante por sinal.

Peguei o link errado. Esse aqui.

http://research.sun.com/jtech/pubs/04-g1-paper-ismm.pdf

J

sergiotaborda:
ViniGodoy:

Não acho estranho que esse método exista. Aliás, também acho que deveria ser obrigatória a execução do gc(). Isso não torna o ambiente não gerenciado, de forma alguma. Ninguém está falando aqui em não ter um garbage collector, ou deletar objetos diretamente.

Mas indirectamente estão dizendo que querem controlar quando ( e possivelmente como) o CG roda. Isso é mesmo que o CG
não ser mais independente da aplicação.

Veja,Iterator.remove tem implementação opcional. Isto significa que vc pode mandar deletar e não vai acontecer. Inesperado talvez
mas a especificação tem que ser assim para dar conta de Arrays.asList().iterator().remove() que não pode remover os itens já que o proxy é imutável. O mesmo acontece com o CG. Porque ele é isolado e vc não o pode comandar (pode sugerir, não comandar) ele tem muita mais flexibilidade. É quase que o principio de hollywood (“don’t call us, we will call you”) so que “don’t call us, we know what to do better than you”. O CG precisa ser isolado (ou seja, náo pode existir forma de o comandar)

A opção de escolher quando o gc vai rodar já existe com esse método System.GC(). Ele resolveu um problema sério de performance que eu tinha num soft aqui. Só estamos comentando sobre a praticidade de ter controle maior sobre o coletor. Por exemplo, de poder escolher como limpar a ram.

http://research.sun.com/jtech/pubs/04-g1-paper-ismm.pdf

O link acima fala das falhas do coletor de lixo, as novas funcionalidades que serão implementadas no próximo.

M

Para entender um pouco mais o CMS(Concurrent Mark-Sweep GC): http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html

Até!

S

Não, não existe. System.gc() dá-lhe a opção de sugerir que o GC rode, não lhe dá a opção de escolher quando roda.
A decisão ainda é do CG e se ele quiser pode simplesmente ignorar a sua sugestão.

Se vc resolveu um problema de performance usando GC o seu sistema não rodará fora da jvm onde o está usando, e portanto não mais será portável. É porque um software java tem que ser portável que ele não pode depender do GC.

Lembra-se da Inversão de Controle ? Aqui é um lugar onde ela já está feita. O que vcs sugerem é totalmente contra o conceito de ter um GC.

O GC não é uma api bacana de gerenciamento de memoria que vc usa nos seu programas C que vc precisa ficar tunando.
O GC é algo à parte. Tão isolado quanto o compilador JIT. Tentar comandar estas coisas em java é como , em C, tentar comandar o que o processador irá fazer a seguir.

A seguir vc vão querer ter controle determinista sobre threads…
Não ha porquê e a sun/jsp faz muito bem em desacoplar as coisas.

J

sergiotaborda:
juliocbq:

A opção de escolher quando o gc vai rodar já existe com esse método System.GC().

Não, não existe. System.gc() dá-lhe a opção de sugerir que o GC rode, não lhe dá a opção de escolher quando roda.
A decisão ainda é do CG e se ele quiser pode simplesmente ignorar a sua sugestão.

Se vc resolveu um problema de performance usando GC o seu sistema não rodará fora da jvm onde o está usando, e portanto não mais será portável. É porque um software java tem que ser portável que ele não pode depender do GC.

Lembra-se da Inversão de Controle ? Aqui é um lugar onde ela já está feita. O que vcs sugerem é totalmente contra o conceito de ter um GC.

O GC não é uma api bacana de gerenciamento de memoria que vc usa nos seu programas C que vc precisa ficar tunando.
O GC é algo à parte. Tão isolado quanto o compilador JIT. Tentar comandar estas coisas em java é como , em C, tentar comandar o que o processador irá fazer a seguir.

A seguir vc vão querer ter controle determinista sobre threads…
Não ha porquê e a sun/jsp faz muito bem em desacoplar as coisas.

Meu soft roda em qualquer so. Não usei nenhum recurso nativo de sistema, então ele é totalmente portável. Só sugeri para que ele ( o GC), limpasse a ram antes de acumular objetos. E resolveu meu problema, e o do vini, no jogo dele.

G

Pois não seria ótimo? :smiley:

B

Alguém tá programando na plataforma errada :lol:

G

Ele roda em qualquer SO, desde que a JVM seja a da Sun, fora dela nada é garantido! Veja bem, não estou discordando da utilidade do System.gc(), mas sim do fato de sua implementação ser opcional. Continue lendo…

sergiotaborda:
Vc está assumindo que 1 desenvolvedor é mais oportuno que um algoritmo desenvolvido e comprovando por
dezenas (senão centenas, quiça milhares ) de desenvolvedores. Isso simplesmente não é verdade.

Olá Sérgio,
Eu sempre pensei dessa forma, achava que chamar o System.gc() era coisa apenas de POGramador que não toma cuidado com performance e usa “força bruta” para tentar liberar um pouquinho de memória.
Mas com os exemplos reais do Vini e do Julio vi que esse comando tem o seu papel quando usado na situação certa, e vou dizer o que penso disso através de uma parábola :slight_smile:

V

Sabe o que tenho notado?

Eu e o julio sempre entramos em debates aqui porque temos vivência em sistemas de tempo real. Mesmo que seja apenas soft real time.

A maioria aqui projeta sistemas comerciais, onde uma espera na casa de segundos é tolerável. Agora, mudem para algo relacionado a vídeo, áudio ou sinalização para hardware, que vão ver que as coisas mudam um pouco de figura.

Mesmo o ser humano é muito mais sensível quando o assunto é aquela “congelada” no meio de um filme ou jogo. Ela pode durar 1/10 de segundo, e você já terá um usuário insatisfeito. Um hardware, então, nem se fala. Alguns milisegundos a mais podem representar uma conexão perdida ou uma negação de serviço. Garanto a vocês que lidamos com software muito otimizado. Para se ter uma idéia, algumas versões dos softwares que eu desenvolvia envolviam horas dedicadas a otimização e profiling.

A analogia com o xixi foi boa. Aliás, bastante perfeita com o problema do gc.

Quanto ao problema das threads: o java nunca prometeu gerenciar threads. Aliás, é uma tarefa que a VM delega ao SO, portanto, nem sequer dá qualquer garantias de que threads sequer existirão.

É possível obter controle determinista sobre threads usando filas e sincronização, embora isso seja uma incrível burrice. Outra opção mais determinista seria reduzir o número de threads ao de processadores, e fazer você mesmo o escalonamento das tarefas no sistema. E essa é uma opção bastante comum em jogos.

V

Vai me desculpar, mas não existe qualquer lógica em seus argumentos. Não há qualquer analogia entre portabilidade e a chamada ao gc. Não estavamos falando em gerenciar o gc na mão, mas em informa-lo que uma sessão crítica do nosso software vai começar e que, no passado, pode haver muita coisa criada e que pode ser coletada. Trata de dizer ao gc que se ele puder limpar agora para não limpar depois, melhor.

E qual é o conceito de se ter um gc?

sergiotaborda:
O GC não é uma api bacana de gerenciamento de memoria que vc usa nos seu programas C que vc precisa ficar tunando.
O GC é algo à parte. Tão isolado quanto o compilador JIT. Tentar comandar estas coisas em java é como , em C, tentar comandar o que o processador irá fazer a seguir.

A seguir vc vão querer ter controle determinista sobre threads…
Não ha porquê e a sun/jsp faz muito bem em desacoplar as coisas.

Engraçado, o próprio gc da sun tem diversas opções de tuning, inclusive com documentação sobre como fazer isso. E o método System.gc() existe. A próxima versão de gc poderá até ter metas de desempenho, fornecidas pelo programador. A argumentação da Sun contra o gc nunca envolveu “o conceito de gc” e sim, dificuldades técnicas de implementação ou liberdade de implementação futura.

S

Vamos lá a ver uma coisa, devo tar falando spranglish…

incovar System.gc() não dá garantia de chamada do CG. Pensemos que temos duas implementações de GC , A e B.
A acata a chamada a gc () como a da sun. B, não. simplesmente ignora.

Agora vc desenvolve um sistema usando a jvm com o cg A. Vc descobre que tem problemas de memoria /performance. Vc então decide chamar system.gc() e descobre que isso resolve o seu problema. Pronto, a sua aplicação está pronta.

Vc manda a aplicação para o cliente que usa uma jvm que corre um cg do tipo B. A sua aplicação continua apresentando o mesmo problema de performance que antes pois a chamada a .gc() não faz nada. A portabilidade da sua aplicação foi pró espaço.
Das duas uma : ou vc estabelece “esta aplicação só funciona na jvm com cg do tipo A” e deixa o cliente se virar para arranjar uma, ou
vc altera a sua aplicação para não precisar invocar o .gc().

É óbvio que .gc() estabelece uma dependencia da JVM. E , como se lembrarão, a jvm da sun não é a única do mundo.

Este cenário é ainda pior em ambiente embarcado. Aqui a chance de usar uma jvm sun é pequena e a chance de estar usando uma jvm tipo B é grande. No cenário embarcado é ainda mais importante a portabilidade e amarrar a performace ao tipo de GC usado por baixo dos panos não é bom. Claro que aqui tb vale a opção “aplicação homologada para o aparelho,X,Y,Z,…”

Existe um outro mundo, e tlv seja esse em que o vini e o julio vivem, em que uma aplicação é feita e otimizada para um certo ambiente. Isso é real e funciona. Até que o ambiente muda e começa tudo de novo. Isso não é mais profiling da aplicação, mas sim do stack inteiro. Isso é tudo muito bom, mas não é o espirito de uma app java. Se vc vive nesse mundo tlv outras plataformas sejam melhores. Java ainda não é para coisa realtime.

O ponto é o seguinte : vc pode informar o gc que agora seria uma boa hora para corre-lo ? sim. isso se chama educação.
A performance da sua aplicação pode depender de chamar ou não o gc ? Não. Isso é uma amarração perigosa. É como usar uma API que só funciona no windows. Deve ser feito ? Não. Pode ser feito ? Pode, mas a custo da aplicação não ser mais portável.
Se a aplicação não é mais portável não ha porque fazê-la em java. Use alguma plataforma nativa ao OS (.NET no windows, C++ no linux , Objetive-C no mac, etc…)

Ok, mesmo sabendo isso ainda prefere java devido a outras facilidades ? Ok. Mas não espere que a especificação da JVM mude para acomodar esse tipo de aplicação que vai contra o costume e os bons princípios da plataforma.

[size=9]
E só um adendo, não de pode dizer que a JVM delega o tratamento de threads para o OS. Não está especificado o que ela faz em relação a isso.
No windows e no linux e na jvm da sun até pode ser que seja assim, mas não podemos partir disse principio ( o que aliás não adiantaria de nada).
Em alguns OS (como no Palm) onde não ha thredas nativas nem processos, a jvm tem que usar green threads. A área de threads é uma das que menos garantias tem. Básicamente vc sabe que run() será chamado. Não sabe como,quando nem por quem.[/size]

V

Ok, sob esse ponto, você está certo. Ele fica vinculado a uma única VM. A sorte é que se vincular a VM da Sun, vc estará se vinculando a aproximadamente 90% das VMs do mecado, pelo menos no caso das aplicações web e desktop. Outros ambientes já não são muito multiplataforma mesmo, e sua aplicação acabará um tanto específica.

Agora, note que hoje o comando só fere uma boa prática de programação justamente pelo seu caráter opcional, que é exatamente o que estamos argumentando contra. Tanto eu quanto o julio sabíamos que esse comando não seria uma panacéia. É na verdade um placebo. Veja que, mesmo que ele seja obrigatório, uma fase de um jogo longa, ou um vídeo longo ainda poderão gerar coletas de lixo… E, realmente, é uma coisa que teremos que tolerar.

Por isso outros defensores de mais controle no gc() sugerem uma forma de paralizar o gc completamente e reativa-lo mais tarde. Essa seria a única forma de garantir algum comportamento de tempo real por algum tempo. Seria isso ir contra o princípio da coleta de lixo, ou do Java? Há muita gente que acha que não e eu me encontro entre elas.

Por outro lado, o java permaneceria inadequado para aplicações de tempo real, pois não é possível manter o coletor de lixo desligado para sempre. Por isso, embora eu ache que esse conceito não seja “filosoficamente antagônico”, não vejo a introdução de um comando desses como algo tão útil assim.

A solução encontrada pela sun foi intermediária e, para o caso do Java, eu considero adequada. Ela vai permitir que o gc assuma compromissos de tempo, dentro da capacidade do hardware e das configurações que estiver rodando. Ele fará isso coletando menos lixo, ajustando melhor o momento das coletas longas, entre outras coisas. Por mim, isso já é mais do que suficiente, e uma solução muito mais elegante do que fazer o programador controlar diretamente o gc. Nada mais é do que melhorar os parâmetros de tuning.

S

ViniGodoy:

Por isso outros defensores de mais controle no gc() sugerem uma forma de paralizar o gc completamente e reativa-lo mais tarde. Essa seria a única forma de garantir algum comportamento de tempo real por algum tempo. Seria isso ir contra o princípio da coleta de lixo, ou do Java? Há muita gente que acha que não e eu me encontro entre elas.

Por outro lado, o java permaneceria inadequado para aplicações de tempo real, pois não é possível manter o coletor de lixo desligado para sempre. Por isso, embora eu ache que esse conceito não seja “filosoficamente antagônico”, não vejo a introdução de um comando desses como algo tão útil assim.

A solução encontrada pela sun foi intermediária e, para o caso do Java, eu considero adequada. Ela vai permitir que o gc assuma compromissos de tempo, dentro da capacidade do hardware e das configurações que estiver rodando. Ele fará isso coletando menos lixo, ajustando melhor o momento das coletas longas, entre outras coisas. Por mim, isso já é mais do que suficiente, e uma solução muito mais elegante do que fazer o programador controlar diretamente o gc. Nada mais é do que melhorar os parâmetros de tuning.

Mas o que importa dessa hsitoria é que isso foi possivel porque é possivel modificar o CG sem ter que modificar as aplicações.

O meu ponto é que o CG é um componente automático, no sentido de “não põe aqui a mão , mané!” (hands-off)
Se for colocada algum método que permite controlar o que o CG faz ou como ou quando faz, ele deixa de ser automático.
Coisas informativas (hints) tudo bem, porque em ultimo caso sempre será o CG a decidir. Isto seria um tuning, mas um tuning não dependente. Neste tipo de API não vejo nenhum mal tecnico. O problema é conceptual como no caso de threads.

A JVM da Sun acata o .gc() se vc chamar com parcimónia, mas será que acata se chamar a cada método ? Convenhamos que se sim, essa não é uma boa implementação do GC. Este tipo de recurso tem que ser protegido do abuso do programador.

O “vedadeiro” real time não se faz com um GC melhor, se faz com uma JVM diferente. A melhor forma de garantir que o GC não afetará o tempo da aplicação é não ter nenhum lixo para coletar. Ora isso só é possivel se não houver nenhum objeto “morto” no heap, e isso só é possivel se o objeto estiver no stack…pois, só que objetos não ficam no stack…ficam ?
Na real time JVM ficam. Nem todos os objetos são aptos a ficam no stack, mas a JVM faz um exercicio interessante ao não popular o heap indescriminadamente. Esta lógica é critica em real time verdadeiro (do qual vidas dependem) mas com o tempo poderá ser o padrão da jvm em que heap e stack passará a ser uma diferenciação semântica. Tudo isto só para dizer que a resposta java para o real time não é (apenas) mudar o GC.

J

A resposta para realtime é não usar máquina virtual. Deve-se fugir de código intermediário em tempo de execução.
Sobre o gc, seria muito interessante essa opção. Cada situação envolve um tipo de ação diferente, e, infelizmente, o coletor de lixo não consegue prever isso.
Poder ter opção, sempre é bom.

S

juliocbq:
A resposta para realtime é não usar máquina virtual. Deve-se fugir de código intermediário em tempo de execução.
Sobre o gc, seria muito interessante essa opção. Cada situação envolve um tipo de ação diferente, e, infelizmente, o coletor de lixo não consegue prever isso.
Poder ter opção, sempre é bom.

Hoje em dia eu não usaria java para realtime, mas o futuro do realtime é sim dentro de uma vm.
A razão é obvia : o controle de tempo não depende do tipo de aplicação . Se com VM conseguimos ter
aplicações mais rápidas que com codigo estáticamente compilado não seria surpreendente que a VM
possa dar garantia de quanto uma execução demoraria. Fora que a analise dinâmica pode encontrar
padrões que podem ser tratados especialmente . Não é coisa para agora, mas no futuro breve ( mais 5 ou 10 anos).

J

Eu espero que sim. Mas sobre tempo e performance de aplicações de máquina virtual serem mais rápidas que código nativo, é pura ilusão. A maioria dos benchmarks que afirmam que um bytecode roda mais rápido que código nativo, estão, na maioria(80%) furados.

Fiz uma pesquisa com benchmarks uma vez, e descobri que a velocidade do bytecode sobre o nativo, se deve a otimização que a máquina virtual faz. Então peguei o mesmo software, este em c++, e aumentei a otimização, nos parâmetros do compilador, para nivel 2(nem setei compilação para processador específico), e tive resultados completamente diferentes. Fiz com vários benchmarks que encontrei no google, que diziam que a vm pode rodar mais rápido que código nativo. E todos os testes falaram o contrário.

E

Além disso, alguns benchmarks tendenciosos comparavam código compilado sem otimização com o Visual Studio 6.0 (compilador bem antiguinho e bem ingênuo, lançado em 1998 ) com o Java 6.0). Se comparar com o mesmo compilador, só que na versão 2008 e código otimizado, o código em C++ costuma ganhar.

V

Um ponto positivo para o Java é o fato de que a VM e os dados de reflection permitem instrumentação do código não intrusiva e de extrema qualidade. Como a obtida no visual VM, por exemplo.

Conseguimos obter diversas aplicações Java mais rápidas do que as feitas em C++, não pelo fato do Java ser uma linguagem nativamente mais rápida, mas pelo fato de ser facílimo instrumentar, descobrir gargalos, corrigir erros e obter algoritmos mais eficientes.

No C++, dificilmente pode-se fazer instrumentação sem inserir instruções de profiling dentro do código.

J

ViniGodoy:
Um ponto positivo para o Java é o fato de que a VM e os dados de reflection permitem instrumentação do código não intrusiva e de extrema qualidade. Como a obtida no visual VM, por exemplo.

Conseguimos obter diversas aplicações Java mais rápidas do que as feitas em C++, não pelo fato do Java ser uma linguagem nativamente mais rápida, mas pelo fato de ser facílimo instrumentar, descobrir gargalos, corrigir erros e obter algoritmos mais eficientes.

No C++, dificilmente pode-se fazer instrumentação sem inserir instruções de profiling dentro do código.

Sim, é verdade, mas os testes são feitos usando programas simples. Normalmente um laço for sem nada dentro, e outras instruções contando tempo e processando calculos matemáticos.

Esse for vazio é descartado pelo otimizador da jvm, enquanto em um compilador, é necessário setar confugurações. Fazendo isso descobri uma série de Benchs inconsistentes, no google.

Normalmente, o resultado é c++ ser 1 tempo, mais rápido que java. E vendo por esse lado, java é a vm mais rápida delas.

V

Outra coisa que observamos é o fato do new de delete do Java ser extremamente rápido.

Faça um teste com a criação e destruição de um objeto dentro de um loop. O C++ tem uma implementação bastante inocente: a cada new, reserva-se memória, a cada delete, apaga-se. Isso é feito por solicitações ao SO, extremamente lentas.

No caso do Java, a VM controla os objetos de vida curta. Quando um objeto é deletado, sua memória não é imediatamente desalocada e só ponteiros da VM são atualizados. Ou seja, equivale a uma deleção de custo próximo ao 0. Se um objeto idêntico é requisitado, essa memória é devolvida, quase instantaneamente.

Isso parte de uma observação de que objetos de vida curta estão muito presentes. Segundo os artigos da sun, eles correspondem a mais de 80% dos casos, em média. Tem mais detalhes desse funcionamento aqui: http://www.ibm.com/developerworks/java/library/j-jtp11253/

Para testar, basta fazer algo como:

for (int i = 0; i < 10000000; i++) { Teste t = new Teste(); delete t; }

Tente usar um objeto com vários campos, para o resultado ser mais evidente, e procure zera-los no construtor, como o java e uma aplicação normal fariam.

No C++, é possível fazer otimizações nesse sentido se você sobrecarregar o new e o delete, e fazer você mesmo um memory manager. E, obviamente, essa é uma tarefa extremamente complexa. Claro, no caso do loop acima, seria possível criar t antes do laço e só zerar os valores de t, ao invés de usar new e delete sempre. Mas isso não seria possível caso t fosse um objeto temporário criado numa função, que estivesse sendo chamada por esse laço.

A implementação do Java, entretanto, come mais memória. É o velho trade-off de velocidade versus memória.

J

ViniGodoy:
Outra coisa que observamos é o fato do new de delete do Java ser extremamente rápido.

Faça um teste com a criação e destruição de um objeto dentro de um loop. O C++ tem uma implementação bastante inocente: a cada new, reserva-se memória, a cada delete, apaga-se. Isso é feito por solicitações ao SO, extremamente lentas.

No caso do Java, a VM controla os objetos de vida curta. Quando um objeto é deletado, sua memória não é imediatamente desalocada e só ponteiros da VM são atualizados. Ou seja, equivale a uma deleção de custo próximo ao 0. Se um objeto idêntico é requisitado, essa memória é devolvida, quase instantaneamente.

Isso parte de uma observação de que objetos de vida curta estão muito presentes. Segundo os artigos da sun, eles correspondem a mais de 80% dos casos, em média. Tem mais detalhes desse funcionamento aqui: http://www.ibm.com/developerworks/java/library/j-jtp11253/

Para testar, basta fazer algo como:

for (int i = 0; i < 10000000; i++) { Teste t = new Teste(); delete t; }

Tente usar um objeto com vários campos, para o resultado ser mais evidente, e procure zera-los no construtor, como o java e uma aplicação normal fariam.

No C++, é possível fazer otimizações nesse sentido se você sobrecarregar o new e o delete, e fazer você mesmo um memory manager. E, obviamente, essa é uma tarefa extremamente complexa. Claro, no caso do loop acima, seria possível criar t antes do laço e só zerar os valores de t, ao invés de usar new e delete sempre. Mas isso não seria possível caso t fosse um objeto temporário criado numa função, que estivesse sendo chamada por esse laço.

A implementação do Java, entretanto, come mais memória. É o velho trade-off de velocidade versus memória.

Não seria possível?

for (int i = 0; i < 10000000; i++) {
  Teste t;
  ZeroMemory(&t,sizeof(t));
}

Imagino aqui o tempo ser bem mais curto. Sendo ZeroMemory escrito diretamente em assembly.

V

Seria, mas considere o caso:

for (int i = 0; i < 10000000; i++) { t.doSomething(); }

E o método doSomething() faz a tal criação e destruição temporárias. No benchmark o problema fica explicito. na vida real, nem sempre.
E considere também que a classe do objeto t não foi implementada por você, mas vem de uma API externa… e aí você já viu o problema.

J

ViniGodoy:
Seria, mas considere o caso:

for (int i = 0; i < 10000000; i++) { t.doSomething(); }

E o método doSomething() faz a tal criação e destruição temporárias. No benchmark o problema fica explicito. na vida real, nem sempre.
E considere também que a classe do objeto t não foi implementada por você, mas vem de uma API externa… e aí você já viu o problema.

Ae sim. Isso é um problema, justamente por eu não ter controle.

A

Eu adoro quando o desenvolvedor utiliza System.gc() dentro do servidor de aplicação. Principalmente quando coloco no parâmetro de inicialização da JVM: -XX:DisableExplicitGC :twisted:

V

Isso só vai fazer com que o comando seja desobedecido sempre. Mas não vai gerar nenhum tipo de erro.
Se o desenvolvedor depende vitalmente dessa chamada, está realmente cometendo um erro fatal.

E detalhe, para esse comando ter efeito, você precisa usar o sinal de +, não o de -. É o problema com opções na negativa. Se você usar com -, estará habilitando o explicit gc (como já é padrão), já que estará desligando o “disable”.

J

ViniGodoy:
Isso só vai fazer com que o comando seja desobedecido sempre. Mas não vai gerar nenhum tipo de erro.
Se o desenvolvedor depende vitalmente dessa chamada, está realmente cometendo um erro fatal.

ainda bem que ele não é meu gerente. Se bem que eu nem trabalho com servidores. A maioria dos softwares são simples, e só controlam hardware.

A

ViniGodoy:
Isso só vai fazer com que o comando seja desobedecido sempre. Mas não vai gerar nenhum tipo de erro.
Se o desenvolvedor depende vitalmente dessa chamada, está realmente cometendo um erro fatal.

Essa é a idéia. Conforme apontado aqui neste tópico, através de System.gc() ele sugere que passe o coletor… simplesmente dou uma forcinha para que a sugestão nunca seja aceita. Confio mais na gestão da coleta pela JVM do que pelo desenvolvedor (em ambientes servidor).

Não é bem assim Vini. Na verdade -XX faz parte do prefixo da diretiva, o que esqueci de digitar foi o + antes do DisableExplicitGC:

-XX:+DisableExplicitGC
J

[quote=Alessandro Lazarotti]

ViniGodoy:
Isso só vai fazer com que o comando seja desobedecido sempre. Mas não vai gerar nenhum tipo de erro.
Se o desenvolvedor depende vitalmente dessa chamada, está realmente cometendo um erro fatal.

Essa é a idéia. Conforme apontado aqui neste tópico, através de System.gc() ele sugere que passe o coletor… simplesmente dou uma forcinha para que a sugestão nunca seja aceita. Confio mais na gestão da coleta pela JVM do que pelo desenvolvedor (em ambientes servidor).

Não é bem assim Vini. Na verdade -XX faz parte do prefixo da diretiva, o que esqueci de digitar foi o + antes do DisableExplicitGC:

-XX:+DisableExplicitGC

existem vantagens e desvantagens.
Como citado, o gc é “burro”. Em muitos casos, você precisa ajustar para sua situação.


http://www.oracle.com/technology/global/lad-pt/pub/articles/brahms-tuning.html

Criado 29 de setembro de 2009
Ultima resposta 1 de out. de 2009
Respostas 54
Participantes 11