Não consegui decidir qual seria a área do fórum caberia esse tópico. Mesmo assim, aí vai minha dúvida:
Gostaria de saber se existe no Java alguma abordagem para trabalhar classes que vão ser criadas e destruídas o tempo todo, por exemplo, classes que representassem pontos na tela. Existe alguma maneira de criar objetos que sejam mais rápidos e consumam menos memória, ou não preciso me preocupar com isso?
A palavra-chave final pode ter algumas implicações de performance - é um assunto que eu não conheço muito bem, mas trata-se do compilador JIT. Porém, imagino que o ganho não vai ser muito dramatico.
Você vai ter quantos objetos? 100 pontos? Um objeto para cada ponto de uma tela de 1024x768 (786432 objetos)? 786432 objetos novos 24 vezes por segundo?
Dependendo do que você está querendo fazer, daria pra usar o padrão Flyweight, ou simplesmente usar um array de tipos primitivos.
Isso mesmo Sami
a melhor maneira de fazer isso eh não criar os objetos o tempo todo
apenas 2 vezes no seu caso…
usando o primeiro conjunto como buffer (zona de trabalho)
e o segundo como zona de exibição ();
vc faz oque tem que fazer na zona de trabalho
e quando acabar (1/24 por segundo…sei la…o teu fps ai)
copia tudo pra zona de exibição…
trabalhando desse jeito vc consegue até separar em Threads a sua implementação
usando uma pra logica e outra apenas pra redesenho…
mais ficar criando objetos o tempo todo não eh legal, e nunca vai ficar rapido…
quer dizer…quem sabe no core256Duo…
É justamente esse meu problema. Pretendo criar um software que desenhe objetos, pontos e figuras geométricas na tela. O problema é que não sei, a princípio, quantos objetos o usuário vai criar.
Devo então criar um objeto para cada ponto? Um objeto novo para cada figura geométrica desenhada?
Ok, inicialmente eu diria que uma quantidade de objetos que o usuário cria manualmente acho que não vai causar grandes problemas em termos de memória. O que é mais problematico (mas talvez também nem seja um problema) é o desempenho de desenhar e redesenhar esse objetos, pontos e figuras geométricas. Se o usuário pode mover uma das suas figuras, ou um ponto da figura, você terá que limpar a tela e redesenhar todos os objetos.
O Flyweight é uma padrão onde você reutiliza objetos imutáveis, mas agora que você explicou seu cenário, não acho mais útil no seu caso.
Pois é cara…tava pensando que tu queria fazer
um Sand da vida…aqueles programas de fisica e fluidos bem legais
Eu tenho um paint aqui meu, e minha implementação ficou bem rapida,
mesmo com varios objetos em cena.
Use o JComponent como base para seus objetos de desenho
e tb para o seu local de desenho.
porque?
bem, porque o swing tem um ótimo sistema de desenho
e suporte a transparencia (setOpaque(false)).
alem de possuir hierarquia de objetos…todo JComponent é um Container
vc pode adicionar um dentro do outro e criar niveis…igual as camadas do photoshop
chamando antes de qualquer coisa o super.paintComponent() e depois desenhando “por cima” da pintura original.
não chamando o super.paintComponent() nunca, ai o desenho todo fica por sua conta.
métodos uteis : getVisibleRect() = area aonde o componente esta para desenhar
Mais já aviso, o jeito correto de mudar a aparencia dos componentes é extendendo uma classe de ComponentUI
da vida… isso para componentes que o usuario vai usar no programa, já para seus objetos de desenho pode sobreescrever mesmo o paintComponent() somente.
Não consegui decidir qual seria a área do fórum caberia esse tópico. Mesmo assim, aí vai minha dúvida:
Gostaria de saber se existe no Java alguma abordagem para trabalhar classes que vão ser criadas e destruídas o tempo todo, por exemplo, classes que representassem pontos na tela. Existe alguma maneira de criar objetos que sejam mais rápidos e consumam menos memória, ou não preciso me preocupar com isso?
[/quote]
Numa primeira abordagem vc não deve se preocupar com isso.
Objetos ocupam a memoria que acupam. não importa qual, será sempre a mesma.
Numa segunda abordagem vc deve pensar qual é o tipo minimo que da conta do recado.
Um ponto na tela.será que preciso de um double ? ou um bigDecimal, ou um array ?
Não será que dois short serve ?
Numa terceira abordagem vc tem que pensar que não é a memória que é lenta, é a leitura e escrita dela.
A criação e destruição do objeto são mais relevantes que o objeto em si.
Se for possivel reaproveitar o objeto e apenas modificar o estado,faça-o. Mas normalmente para objetos de valor
como Pontos, isso não é possivel. Neste nivel tem que pensar no tipo de objeto que está usando.
Bom, vamos esclarecer alguns mals entendidos. Colocar final pode ter algum impacto em performance, mas ele geralmente é irrisório. Na verdade, há muito mito sobre o final, assim como há mitos também sobre a palavra const, do C++. Veja o artigo do próprio Brian Goetz sobre isso:
O padrão flyweight não se aplica a esse caso. Ele só é aplicado quando você tem um grupo de objetos que podem compartilhar uma característica imutável e pesada. Um exemplo. Suponha que você está fazendo um jogo de “space invaders”. Nesse jogo, há várias naves idênticas. Carregar várias cópias da imagem da nave seria um despedício de tempo e memória. Usa-se então o padrão flyweigth para que as naves compartilhem essa imavel (imutável e pesada), separando isso da parte mutável (posição da imagem na tela).
Antes de falar em otimização, verifique que você tem um problema de performance. Não otimize se não tiver. Estamos falando em quantos pontos? 1, 10, 1000, 1.000.000?
Criar e destruir objetos de mesma estrutura (como os pontos) é uma tarefa muito barata em Java. Isso porque o heap do java irá manter a memória alocada e o custo de pedir e devolver esse dado para o SO, que incomoda tanto os programadores do C++, é muito pequeno aqui. É claro que haverá um pequeno tempo de “warmup”, mas duvido muito que ele será perceptível. Para mais informações: http://www.ibm.com/developerworks/library/j-jtp01274.html
Se tiver um problema, rode um profiler para identificar onde. A maior parte dos gargalos pode ser resolvida com otimizações simples, sem envolver mandraquismos. Um ótimo profiler é o do Netbeans: http://profiler.netbeans.org/docs/help/index.html
Se você mexer no código e não resolver, desfaça a modificação. Dê sempre preferência a um código claro, no lugar de um otimizado. Portanto, se não for absolutamente necessário, não otimize. Se você não estiver fazendo nada animado, provavelmente só usar o swing com cautela te resolverá o problema, e dificilmente você terá que se preocupar com criação/destruição de objetos ou técnicas de otimização.
O swing é legal e rápido, utiliza por padrão double buffering, evita flickering, etc. Mas, para um número grande de pontos em movimento, usar o paintComponent não vai ajudar muito. Você precisará ter mais controle sobre o ciclo de pintura. O swing não garante que a tela será repintada toda vez que o repaint é dado, pois uma técnica chamada event coalescing. Para aplicações de janela, essa técnica evita que muito processamento seja feito desnecessariamente, já que componentes não mudam o tempo todo. Para um efeito de vídeo, ela incomoda.
Então, o que se faz é desabilitar totalmente esse ciclo e usar uma técnica chamada direct painting. Esse tutorial explica como fazer isso: http://www.cokeandcode.com/info/tut2d.html
Entretanto, se você não está fazendo vídeo, pontos em movimento, como o colega falou, dificilmente você sequer chegará a esse ponto.
Por fim, se sua aplicação vai gerar uma quantidade absurdamente grande de pontos, recomendo que você parta para um pipeline gráfico que use diretamente a placa de vídeo. Um exemplo disso é desenhar os pontos usando OpenGL. Você pode fazer isso através da JOGL: https://jogl.dev.java.net/
Há muito material sobre opengl no meu blog, que pode ser facilmente adaptado para java. A vantagem é que aqui a aceleração de hardware será realmente percebida, principalmente se você tiver uma placa de vídeo. É possível renderizar mais de 1 milhão de triângulos em 10 FPS com uma antiga GeForce 4400MX (numa aplicação devidamente otimizada, lógico)…
Se ainda faltar velocidade, algumas técnicas podem otimizar ainda mais:
Use pequenos triângulos com textura no lugar de pontos. Use somente luz ambiente;
Use VertexBuffers ao invés dos métodos mastigados do OpenGL;
Procure desenhar pontos próximos e de mesma característica ao mesmo tempo;
Tente maximizar o número de pontos num único batch para a placa de vídeo.
Muito obrigado pela dica. Certamente irá ajudar bastante.
O software que pretendo desenvolver é um programa de Geometria interativo em que o usuário manipula figuras geométricas na tela. Tudo fica um pouco mais complexo por que ainda não estou tão familiarizado com o Swing. Por exemplo, manipular botões, caixas de texto em uma IDE como o Netbeans e atribuir comportamentos para esses controles é relativamente fácil. O problema é quando você precisa refinar mais o comportamento, gerar componentes personalizados…
Mas gradativamente, com as dicas que recebi, tenho certeza que a dificuldade inicial irá desaparecer.