Memoria Heap

8 respostas
J

Bom Dia galera, estou criando um programa para gerar um arquivo de funcionarios no formato csv, mas minha base é muito grande, tenho em media uns 500 mil registros por cada arquivo. Gostaria de saber se a alguma forma de otimizar este codigo. Ou se esta estourando por eu armazenar tudo apenas em uma String.Valeu a atenção e aceitamos sugestões. Valeu pessoal e segue o codigo.

public byte [] exportCVSPontoColab(List<Funcionario> dados) throws IOException{
  
       StringBuilder sb = new StringBuilder();
       
         for(Funcionario f : dados){
           sb.append(1).append(";");
           sb.append(f.getFuncionarioPK().getEmpresa()!=null?f.getFuncionarioPK().getEmpresa():"").append(";");
           sb.append(f.getFuncionarioPK().getUnidadeMestre()!=null?f.getFuncionarioPK().getUnidadeMestre():"").append(";");
           sb.append(f.getFuncionarioPK().getUnidade()!=null?f.getFuncionarioPK().getUnidade():"").append(";");
           sb.append(f.getFuncionarioPK().getRegistro()!=null?f.getFuncionarioPK().getRegistro():"").append(";");
           sb.append(f.getTipo()!=null?f.getTipo():"").append(";");
           sb.append(f.getFunome()!=null?f.getFunome():"").append(";");
           sb.append(f.getCarteira()!=null?f.getCarteira():"").append(";");
           sb.append(f.getSerie()!=null?f.getSerie():"").append(";");
           sb.append(f.getDtadmissao()!=null?f.getDtadmissao().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getTpant()!=null?f.getTpant():"").append(";");
           sb.append(f.getRegant()!=null?f.getRegant():"").append(";");
           sb.append(f.getCcusto()!=null?f.getCcusto():"").append(";");
           sb.append(f.getDepto()!=null?f.getDepto():"").append(";");
           sb.append(f.getTurno()!=null?f.getTurno():"").append(";");
           sb.append(f.getCargo()!=null?f.getCargo():"").append(";");
           sb.append(f.getLinha()!=null?f.getLinha():"").append(";");
           sb.append(f.getDtafastamento()!=null?f.getDtafastamento().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getAfastamento()!=null?f.getAfastamento().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getDtretorno()!=null?f.getDtretorno().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getOpcao()!=null?f.getOpcao():"").append(";");
           sb.append(f.getImprel()!=null?f.getImprel():"").append(";");
           sb.append(f.getFlag_horario()!=null?f.getFlag_horario():"").append(";");
           sb.append(f.getFlag_refeicao()!=null?f.getFlag_horario():"").append(";");
           sb.append(f.getDtnasc()!=null?f.getDtnasc().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getCuil()!=null?f.getCuil():"").append(";");
           sb.append(f.getJornada_trabalho()!=null?f.getJornada_trabalho():"").append(";");
           sb.append(f.getFunbanco()!=null?f.getFunbanco():"").append(";");
           sb.append(f.getFunprod()!=null?f.getFunprod():"").append(";");
           sb.append(f.getFundias()!=null?f.getFundias():"").append(";");
           sb.append(f.getConceito()!=null?f.getConceito():"").append(";");
           sb.append(f.getObsconceito()!=null?f.getObsconceito():"").append(";");
           sb.append(f.getSexo()!=null?f.getSexo():"").append(";");
           sb.append(f.getArmario()!=null?f.getArmario():"").append(";");
           sb.append(f.getFreqdiar()!=null?f.getFreqdiar():"").append(";");
           sb.append(f.getFuhor_comp()!=null?f.getFuhor_comp():"").append(";");
           sb.append(f.getChefia()!=null?f.getChefia():"").append(";");
           sb.append(f.getTipoJornada()!=null?f.getTipoJornada():"").append(";");
           //Quando se faz o parse de Double para string e retira o ponto gera tres numeros a mais na String que é tratado na substring
           sb.append(f.getPis()==null||f.getPis().toString().length()<5?"":String.valueOf(f.getPis()).replaceAll("\\.","").substring(0,String.valueOf(f.getPis()).replaceAll("\\.","").length()-4)).append(";");
           sb.append(f.getVnc()!=null?f.getVnc():"").append(";");
           sb.append(f.getCpf()!=null?f.getCpf():"").append(";");
           sb.append(f.getAproximacao()!=null?f.getAproximacao().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getDataInclusao()!=null?f.getDataInclusao().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getDataAlteracao()!=null?f.getDataAlteracao().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getDataFechamento()!=null?f.getDataFechamento().toString().replaceAll("-","/"):"").append(";");
           sb.append(f.getDataJornada()!=null?f.getDataJornada().toString().replaceAll("-","/"):"").append(";");
           sb.append("\n");     
         }
    
    return sb.toString().getBytes();
  }

8 Respostas

ViniGodoy

E você não grava cada linha diretamente no arquivo por que…?

guilherme.dio

Nossa, com toda certeza vai estourar a memória guardando 500 mil registros com dezenas de campos em uma String !!

Muda isso ai, grava direto no arquivo, e arruma esses singleLine Ifs, muita verificação seguida.

J

Não gravei por dois motivos:
1- o padrão da empresa é sempre devolver um array de bytes nas classes report .
2 - O arquivo vai ser devolvido via response.getOutputStream() , onde imediatamente o arquivo vai der disponibilizado para download.

Mas será que eu poderia escrever direto em um arquivo e depois disponibilizar para download?

E

Quanto a padrões, você pode negociar com a sua empresa…
Em particular, acho muito tosco o report retornar um array de bytes. Você sabe que existem arquitetos e arquitetos.
O mais comum seria o método que vai realizar o report receber um OutputStream ou Writer, para escrever nele (o OutputStream pode ser um socket, ou um arquivo, ou sei lá o quê - eu me lembro do tempo em que tinha de escrever métodos que podiam gerar um arquivo criptografado ou não, só mudando o OutputStream para um CipherOutputStream. )

O correto, nesse caso, seria jogar diretamente o CSV no outputStream. Você não precisa gastar um centavo de memória.

Imagine 500.000 registros, cada qual com 200 caracteres (400 bytes), isso dá 200 MB por relatório :frowning: - e imagine 20 pessoas pedindo esse relatório ao mesmo tempo. A memória vai arriar na hora.

R

Voce deve negociar com sua empresa sobre este padrão, com certeza voce tem um problema bem grande, tente montar uma reuniao para achar a melhor solução.
Este é apenas um relatorio de onde vem os problemas se memoria, tem mais relatorios no sistema ou é so esse?

J

Olá obrigado pela ajuda de todos, conversei com o analista e vamos conversar com o cliente para podermos arranjar uma outra solução, até mesmo porque como o bd está em rede externa e não temos acesso direto a produção, usamos VPN ,o trafego tbm fica muito lento por ser uma quantidade considerável de informações. Este é o unico relatorio desde porte e será gerado apenas uma vez ao dia.E tbm vou alterar para escrever direto em um arquivo, para que não prejudique a memoria.

J

Agradeço novamente a ajuda de todos.

E

juniorsml:
Olá obrigado pela ajuda de todos, conversei com o analista e vamos conversar com o cliente para podermos arranjar uma outra solução, até mesmo porque como o bd está em rede externa e não temos acesso direto a produção, usamos VPN ,o trafego tbm fica muito lento por ser uma quantidade considerável de informações. Este é o unico relatorio desde porte e será gerado apenas uma vez ao dia.E tbm vou alterar para escrever direto em um arquivo, para que não prejudique a memoria.

Se o banco está em rede externa, talvez fosse interessante que tal relatório fosse criado pelo próprio banco de dados (costuma haver ferramentas para isso) e houvesse uma batch que gerasse esse relatório (é em formato CSV, não?) Então até dá para, por exemplo, solicitar a compactação desse relatõrio antes da transmissão pela VPN, para poder recebê-lo mais rapidamente.

Criado 6 de julho de 2012
Ultima resposta 6 de jul. de 2012
Respostas 8
Participantes 5