Desempenho em Manipulação de Muitos Arquivos

8 respostas
andreflashen

Ola a todos,
como o proprio assunto ja diz, estou com um problema com desempenho na manipulacao de arquivos…
na verdade o que procuro aqui eh uma melhor abordagem para utilizar com a seguinte situacao:

tenho 200 e poucos arquivos texto que sao logs gerados de um gateway de telefonia, somando as linhas de todos os arquivos da umas 8 milhoes de linhas…
eu preciso ler esses arquivos e persistir essas linha no banco de dados (isso a grosso modo)
na realidade cada linha pode estar ligada a outras 3 por meio de um ID que vem em hexadecimal no arquivo, entao o ideal era varrer todas a linhas, juntar as que forem ‘juntaveis’ por assim dizer e por fim persistir toda essa informacao em um Banco de Dados (nao necessariamente relacional) tudo isso com o maximo de desempenho possivel!

sendo assim busco qual seria a melhor abordagem para se tirar o maximo em velocidade (e nao estourar a memoria evidentemente) nesse processo!

obrigado!

8 Respostas

alxdre.pestana

andreflashen:
Ola a todos,
como o proprio assunto ja diz, estou com um problema com desempenho na manipulacao de arquivos…
na verdade o que procuro aqui eh uma melhor abordagem para utilizar com a seguinte situacao:

tenho 200 e poucos arquivos texto que sao logs gerados de um gateway de telefonia, somando as linhas de todos os arquivos da umas 8 milhoes de linhas…
eu preciso ler esses arquivos e persistir essas linha no banco de dados (isso a grosso modo)
na realidade cada linha pode estar ligada a outras 3 por meio de um ID que vem em hexadecimal no arquivo, entao o ideal era varrer todas a linhas, juntar as que forem ‘juntaveis’ por assim dizer e por fim persistir toda essa informacao em um Banco de Dados (nao necessariamente relacional) tudo isso com o maximo de desempenho possivel!

sendo assim busco qual seria a melhor abordagem para se tirar o maximo em velocidade (e nao estourar a memoria evidentemente) nesse processo!

obrigado!

Olá Boa noite!
No seu caso utilize o Scanner…
Já tive uma situação similar e com BufferedReader sempre havia estouro de memória e outra que a leitura do arquivo estava durando cerca de 40 minutos.
Com scanner reduzi para menos de 10 segundos :wink:

//Efetuando leitura no arquivo e convertendo em String
FileInputStream in = new FileInputStream(arquivo);   
Scanner scanner = new Scanner(in);   
scanner.useDelimiter("\\n"); 
				            
StringBuffer sbf = new StringBuffer();   
while (scanner.hasNext()) {     
         String readLine = scanner.next();     
	 sbf.append(readLine);   
}   
String cConteudo = sbf.toString();
scanner.close();
in.close();

Abraço

giovanni_dalfre

Da uma lida em: http://java.sun.com/docs/books/performance/1st_edition/html/JPIOPerformance.fm.html

Testei alguns algorítimos para LER um arquivo txt com 15kb e retornar em uma variavel.

Scanner (exemplo do amigo acima) : 2600 milissegundos.

BufferedInputStream : 2250 milissegundos.

BufferedInputStream customizado : 200 milissegundos.

Sendo o ultimo:

byte[] bbuf = new byte[1024];
	 InputStream in = new BufferedInputStream(new FileInputStream("c:/texto.txt"));
         OutputStream out = new ByteArrayOutputStream();
		  
        int bytesRead = 0;
       
        while ((bytesRead = in.read(bbuf)) != -1) {
             out.write(bbuf, 0, bytesRead);
        }
        in.close();
        out.close();
        xml = out.toString();

Oque torna esse algorítimo rápido é que ele, no lugar de 1byte por vez, ele lê 1Kb por vez.

alxdre.pestana

giovanni_dalfre:
Da uma lida em: http://java.sun.com/docs/books/performance/1st_edition/html/JPIOPerformance.fm.html

Testei alguns algorítimos para LER um arquivo txt com 15kb e retornar em uma variavel.

Scanner (exemplo do amigo acima) : 2600 milissegundos.

BufferedInputStream : 2250 milissegundos.

BufferedInputStream customizado : 200 milissegundos.

Sendo o ultimo:

byte[] bbuf = new byte[1024];
	 InputStream in = new BufferedInputStream(new FileInputStream("c:/texto.txt"));
         OutputStream out = new ByteArrayOutputStream();
		  
        int bytesRead = 0;
       
        while ((bytesRead = in.read(bbuf)) != -1) {
             out.write(bbuf, 0, bytesRead);
        }
        in.close();
        out.close();
        xml = out.toString();

Oque torna esse algorítimo rápido é que ele, no lugar de 1byte por vez, ele lê 1Kb por vez.

Nossa giovanni_dalfre, legal cara gostei… Você arrasou agora…
Nunca fiz um comparativo a nível de detalhes e a sua solução é a melhor.

Abraço

E
na realidade cada linha pode estar ligada a outras 3 por meio de um ID que vem em hexadecimal no arquivo, entao o ideal era varrer todas a linhas, juntar as que forem 'juntaveis' ...

Essa é a parte chata da coisa (não exatamente ler o arquivo do disco).
Qual é o tamanho total dos arquivos a serem relacionados, em bytes?

J

entanglement:
na realidade cada linha pode estar ligada a outras 3 por meio de um ID que vem em hexadecimal no arquivo, entao o ideal era varrer todas a linhas, juntar as que forem 'juntaveis' ...
Essa é a parte chata da coisa (não exatamente ler o arquivo do disco).
Qual é o tamanho total dos arquivos a serem relacionados, em bytes?

Exatamente… se você pode ter 8 milhões de linhas e precisa da informação de 4 linhas para gravar em torno de 2 milhões de informações, será necessário um pré-processamento.

Se este pré-processamento não for necessário, pode-se verificar o id de cada item antes de persistir as informações, mas isso com certeza seria lento.

Eu pensaria em fazer um pré-processamento da seguinte forma:

  1. Armazenaria em memória todos esses IDs das 8 milhões de linhas, com o ponteiro do arquivo inicial e final de cada uma delas. Durante o armazenamento tentaria localizar as semelhanças dos ids, porém ainda não existiria persistência.
  2. Se essa lista em memória for consumir muito recurso (memória), uma gambiarra seria utilizar arquivos temporários para este armazenamento. Isso evitaria o consumo de memória e com apenas 1 unica leitura em todo o arquivo você localizaria as semelhanças.
  3. Processaria essa lista de semelhanças (pré-processamento) obtendo as informações diretamente dos ponteiros usando RAF e seek… Faria a persistência das informações.

Nunca processei algo tão grande. Não sei se essa seria a melhor abordagem.

A persistência pode ser até mesmo em outro arquivo texto. Depende o que você precisa fazer com isso…

Luizao

Que tal jogar os arquivos pra um banco de dados? Parseia cada linha, e insere numa tabela. Depois vc agrupa pela key e desnormaliza. Deixa o banco fazer o trabalho pesado =)

J

Não sei se isso seria uma boa idéia devido ao grande volume de informações… além de que pode consumir recursos violentos armazenar 8 milhões de registros no banco de dados.

Luizao

Acho que não vai ocupar taaanto espaço… só para efeito de comparação, tenho uma tabela aqui com 10 milhões de registros, ocupando menos de 1gb no postgres. Claro que isso depende da estrutura da tabela, mas já dá pra vc ter uma idéia do espaço que pode ser necessário, se resolver ir por esse lado :).

Criado 10 de setembro de 2012
Ultima resposta 11 de set. de 2012
Respostas 8
Participantes 6