Teste Desempenho IO Buffered vs FileChannel

5 respostas
R

Oi pessoal,

Desenvolvi um projeto com algumas classes e métodos para facilitar a vida no que diz respeito a operações de IO.
Exportei como arquivo jar.
Para fazer minha classe CopiaArquivo, por exemplo, utilizei a classe FileChannel da api do java.

Depois de terminar o projeto me dei conta que havia utilizado esta classe arbitrariamente, sem me preocupar se este seria o melhor jeito.

Então resolvi fazer uns testes, comparando a classe FileChannel com as clássicas Bufffered.

Vejam o seguinte código:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.channels.FileChannel;
import java.util.Date;
public class Main {

	
	public static void main(String[] args)throws IOException {
		long inicioChannels = new Date ().getTime();
		testWithChannels();
		long terminoChannels = new Date().getTime();
		System.out.println ("Tempo channels: " + (terminoChannels - inicioChannels));
		
		long inicioBuffered = new Date ().getTime();
		testWithBufferedClasses();
		long terminoBuffered = new Date().getTime();
		System.out.println ("Tempo Buffered: " + (terminoBuffered - inicioBuffered));
		
		new File ("D:\\destinoChannel\\testePerformance.txt").delete();
		new File ("D:\\destinoBuffered\\testePerformance.txt").delete();

	}
	
	private static void testWithChannels ()throws IOException{
		FileChannel srcChannel = new FileInputStream("D:\\origemChannel\\testePerformance.txt").getChannel(); 
		FileChannel dstChannel = new FileOutputStream("D:\\destinoChannel\\testePerformance.txt").getChannel(); 
		dstChannel.transferFrom(srcChannel, 0, srcChannel.size()); 
		srcChannel.close(); 
		dstChannel.close();
		
		
	}
	private static void testWithBufferedClasses ()throws IOException{
		BufferedReader reader = new BufferedReader (new FileReader (new File ("D:\\origemBuffered\\testePerformance.txt")));
		PrintWriter writer = new PrintWriter (new FileWriter (new File ("D:\\destinoBuffered\\testePerformance.txt")));
		char [] buffer = new char [1024];
		int lido = 0;
		while ((lido = reader.read(buffer)) != -1){
			writer.write(buffer);
		}
		writer.flush();
		writer.close();
		reader.close();
	}

}

Conclusões do teste:

Para arquivos pequenos, de até 100 Kb, o tempo de execução de ambos os métodos é praticamente o mesmo.

Para arquivos maiores, o método que usa a classe FileChannel começa a levar vantagem.

Com um arquivo de 15 megas, o tempo de fileChannel foi 200 e o das classe Buffered foi 800. E esta diferença aumenta conforme aumenta o tamanho do arquivo.

Também testei colocar BufferedWriter no lugar de PrintWriter. O tempo piorou drasticamente.

5 Respostas

C

E está totalmente correto o teste.
Se vc vai ficar lendo sequencialmente um arquivo, porque usar um *Buffered?
Necessidade nenhuma, ainda mais se comparar com o FileChannel, que é do Java NIO, enquanto o Buffered é do século passado.

R

Adicionei o seguinte método ao teste:

private static void testWithStreams ()throws IOException{
		InputStream in = new FileInputStream("D:\\origemStream\\testePerformance.txt");
        OutputStream out = new FileOutputStream("D:\\destinoStream\\testePerformance.txt");   
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
	}

Resultados para um arquivo de 37 megas:

1 vez:
Tempo channels: 625
Tempo Buffered: 4437
Tempo Stream: 4110

2 vez:
Tempo channels: 656
Tempo Buffered: 2469
Tempo Stream: 2281

3vez:
Tempo channels: 625
Tempo Buffered: 4047
Tempo Stream: 4766

4vez:
Tempo channels: 625
Tempo Buffered: 3891
Tempo Stream: 4562

5vez:
Tempo channels: 641
Tempo Buffered: 2531
Tempo Stream: 2250

M

Diferença massante… E com Scanner/Writer?

public static void testWithScanner() throws IOException {            
	Scanner in = new Scanner("D:/origemStream/testePerformance.txt");
	PrintWriter out = new PrintWriter(                               
			"D:/destinoStream/testePerformance.txt");                
	while (in.hasNextLine()) {                                       
		out.println(in.nextLine());                                  
	}                                                                
	out.flush();                                                     
	in.close();                                                      
	out.close();                                                     
}

Pode testar e postar os resultados? :slight_smile:

R

marcobiscaro2112:
Diferença massante… E com Scanner/Writer?

public static void testWithScanner() throws IOException {            
	Scanner in = new Scanner("D:/origemStream/testePerformance.txt");
	PrintWriter out = new PrintWriter(                               
			"D:/destinoStream/testePerformance.txt");                
	while (in.hasNextLine()) {                                       
		out.println(in.nextLine());                                  
	}                                                                
	out.flush();                                                     
	in.close();                                                      
	out.close();                                                     
}

Pode testar e postar os resultados? :)

na verdade, desta forma seu scanner está lendo a string que vc passou para ele como parametro. É preciso construir um Scanner com uma stream para que ele leia de um arquivo. Logo creio que o desempenho será praticamente o mesmo do teste realizado diretamente com streams.

M

rod.attack:
marcobiscaro2112:
Diferença massante… E com Scanner/Writer?

public static void testWithScanner() throws IOException {            
	Scanner in = new Scanner("D:/origemStream/testePerformance.txt");
	PrintWriter out = new PrintWriter(                               
			"D:/destinoStream/testePerformance.txt");                
	while (in.hasNextLine()) {                                       
		out.println(in.nextLine());                                  
	}                                                                
	out.flush();                                                     
	in.close();                                                      
	out.close();                                                     
}

Pode testar e postar os resultados? :)

na verdade, desta forma seu scanner está lendo a string que vc passou para ele como parametro. É preciso construir um Scanner com uma stream para que ele leia de um arquivo. Logo creio que o desempenho será praticamente o mesmo do teste realizado diretamente com streams.


Verdade aqui ele lê da String… bem observado. Obrigado pela correção. O correto seria:

public static void testWithScanner() throws IOException {            
	Scanner in = new Scanner(new File("D:/origemStream/testePerformance.txt")); // agora sim!
	PrintWriter out = new PrintWriter(                               
			"D:/destinoStream/testePerformance.txt");                
	while (in.hasNextLine()) {                                       
		out.println(in.nextLine());                                  
	}                                                                
	out.flush();                                                     
	in.close();                                                      
	out.close();                                                     
}
Criado 13 de janeiro de 2010
Ultima resposta 15 de jan. de 2010
Respostas 5
Participantes 3