Performance, camadas e construtores

12 respostas
marcioa1

Olá.

Tenho um grave problema de performance na minha aplicação.

Não estou considerando o tempo de abrir a conexão. Ela é aberta uma vez, os objetos são criados e depois eu a fecho.

Acontece que tenho dois pacotes, um para negócio e outro para banco.

Uma classe tem como atributo outra classe. Esta tem como atributo, outras classes.

No contrutor da classe de negócio Atendimento, eu chamo o correspondente da classe de banco. Esta classe de banco chama o contrutor das classes Prestador e Procedimento, que são suas proprietades . Cada uma destas classes chama seu respectivo contrutor na classe de banco etc …

class Atendimento;

   private int codigo;
   private Internacao internacao;
...

class Internacao;
   private int codigo;
   private Prestador prestadorPrincipal;
   private Prestador localDeAtendimento;
   private Procedimento procedimentoRealizado;

....

Cada uma destas classes existe em ambas as camadas. Para cada classe, há um comando sql ( statement, resultset ). sendo que a conexão é static.

Esta forma de distribuição está, ao meu ver, criando um problema de performance. Meus colegas querem que eu faça um só select GRANDÃO, e a partir dai eu monta cada classe ??? Acho que ficaria ruim, mas talvez a performance fosse melhor.

Existe algum framework (uso o banco Caché, e não sei de nenhum dialeto específico para o Hibernate) que agilizasse todo este processamento? Spring ? Uma luz por favor. Meu relatório ( em PDF ) pode durar até sete horas !!! São mil médicos fazendo dezenas de procedimentos cada. Cada procedimento dura cerca de dois seguindos para ser construido.

Obrigadíssimo,

Márcio

12 Respostas

thiagossantos

tenta usar o java -Xprof

mais informacoes no command digita java -X

ele informa a utilizacao da cpu e tempo q o programa gasta, ai vc sabe onde o código está mais lento e consome mais cpu… ai vc sabe o q precisa melhorar, saca?

isso resolve???
(to no basico ainda, mas ja ouvi falar desse negocio ai e funcionou qnd quis calcular uns numeros primos aki pra otimizar o rendimento)

[]'s

Thiago

marcioa1

Thiago,

Vou ver a dica, mas meu problema não é saber quanto tempo ele gasta, mas como reduzir este tempo.

Obrigado,

Márcio

thiagossantos

mas se vc puder usar ele informa em porcentagem a qnt de processamento necessario pra cada metodo ou classe. Aí vc sabe onde precisa alterar o código pra ele ficar mais rápido.

Ele n diz o que vc precisa fazer, mas pelo menos diz onde.

(Fui inventar de assistir uma aula na universidade ontem como ouvinte… o prof tava ensinando isso entre outras coisas)

marcioa1

Vou tentar e deposi te digo

Márcio

mcampelo

Você consegue identificar onde está o seu problema?

Primeiro você precisa identificar se o problema está no banco de dados (veja o tempo de execução de cada select) ou no processamento (aí o problema está no Java).

Sem definir exatamente onde está o seu problema (BD, Lógica de Negócios, GC), acho que não dá nem para começar a trabalhar na solução.

Anyway … Se um select apenas consegue resolver o problema de milhares de pequenos selects, por que não ir por esse caminho?

Outra idéia quando você tem problema de performance é utilizar produtos que ajudam a entender onde está o problema.

Algumas referências:

http://www.javaperformancetuning.com/
http://java.sun.com/docs/books/performance/

[]'s
Marco Campêlo

marcioa1

Marco,

O problema com o único select é que eu gostaria de criar meus objetos em um único lugar. Se começar a criar selects em vários lugares criando os mesmos tipos de objetos, creio que haverá confusão.

O problema é: para criar uma instância de um objeto composto por vários objetos, eu executo um select para criar uma instância de cada objeto que é propriedade do objeto maior, e depois associo estes pequenos objetos ao objeto maior.

Continuo confuso ?

Márcio

renatosilva

Para cada registro numa tabela você cria um Atendimento, sendo que pega os registros relacionados a esse “cada registro” em outra tabela e cria os Internacao. E para cada um destes, faz a mesma coisa, buscando em outra tabela os registros relacionados à Internacao atual e criando os objetos Procedimento e Prestador referentes? É isso???

marcioa1

É isto.

Eu só crio os objetos na classe ( óbvio ) que chama um método na classe de banco para dá o select. Em um objeto composto por vários outros objetos, para cada um, criao o statement, o resultSet, atribuir cada campo do resultset para o campo do objeto de transporte ( DTO ) e retornar a classe de negócio que chamou o método de busca no banco, para atribuir cada campo da classe DTO para a classe que está sendo instanciada.

Ufa…

Tá errado ?

Márcio

mcampelo

E onde está o problema de performance?

No fato de fazer N queries?

Se esse for o problema, deixe de lado o purismo e resolva tudo com um SQL único. Por que não?

OO, patterns e afins podem ser muito bonitos mas acho que não podemos esquecer que o objetivo do software é resolver o problema do usuário.

Eu não pensaria 2 vezes em sacrificar o design do meu código para ganhar em performance (óbvio, se o ganho for substancial).

[]'s
Marco Campêlo

louds

Usar um select com vários joins para otimizar o acesso ao banco é uma técnica muito usada, eager-loading. Se round-trip-time para o teu banco de dados for significativo usar eager-loading é indispensavel. No oracle verifique isso com um “select sysdate from dual”. Supondo que você precise de mil queries e o rtt seja de 50ms, o tempo perdido só com transmissão de rede são 50 segundos.

Os problemas do eager são desenmaranhar os objetos do ResultSet e retornar um volume monstruoso de dados. Quanto ao volume, só verificando no seu cenário, já o algoritmo para fazer isso, da forma como as ferramentas de ORM fazer, é +/- o seguinte:

clear cache
for r in select * from a, b where ...
  if r[a].pk not in cache 
    cache.add new A(r[a])
  if r[b].pk not in cache 
    cache.add new B(r[b])

Espero que o pseudo-código esteja claro o suficiente.

tRuNkSnEt

Não sei se voce esta espalhando as sql pelo seu codigo, tente junta-las em um unico lugar, quem sabe usando .properties ou ate mesmo com alguma outra tecnologia mais alem. Assim voce pode administrar melhor o seu caso, voce vai poder enchegar melhor suas sql tirando a repetição de algumas ou quem sabe juntando umas com as outras como ja foi mencionado.

Obs: Não li todos os post :oops:

renatosilva

marcioa1:
O problema é: para criar uma instância de um objeto composto por vários objetos, eu executo um select para criar uma instância de cada objeto que é propriedade do objeto maior, e depois associo estes pequenos objetos ao objeto maior.

marcioa1:
Em um objeto composto por vários outros objetos, para cada um, criao o statement, o resultSet, atribuir cada campo do resultset para o campo do objeto de transporte ( DTO ) e retornar a classe de negócio que chamou o método de busca no banco, para atribuir cada campo da classe DTO para a classe que está sendo instanciada.

Márcio, eu entendi mal ou você dá um select de um registro só no construtor da classe para criar UMA instância da própria classe , ou você dá o select na classe pai, que cria os objetos propriedades (o select não é para a própria classe e sim para os objetos propriedade)???

Criado 27 de abril de 2005
Ultima resposta 27 de abr. de 2005
Respostas 12
Participantes 6