`

Java IO性能测试

 
阅读更多
在JDK 1.4版本中,新增加了nio包,目前在于提升IO速度。 不过大家都知道,增加了nio包之后,旧的io包其实也进行了重写。就算不显示的使用nio包,也可以明显的感觉到速度的提升。

而且很多人在使用io包的时候,也只是知道装饰一个Buffer的InputStream或者OutputStream,速度会更快。

那么,在这几者之间,速度上到底有差距没?差距有多大?我们将进行一次IO操作的性能测试。


测试的IO操作为,普通的文件读写(不带Buffer),带Buffer的文件读写,使用nio的管道的普通文件读写,使用nio的管道的随机文件读写。


先写一个TestIO测试类。

/**
 * 测试IO的抽象类
 * @author wing
 * @date 2012/7/22
 */
public abstract class TestIO {
    private long start, time;
	
	public void testTime(){
		start = System.nanoTime();
		test();
		time = System.nanoTime() - start;
		System.out.format("%.3f\n", time/1.0e9);
	}
	
	protected abstract void test();
}

用来测试test方法的操作耗时。


然后是各种IO操作的FileIO类。

package org.wing.nio.test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

/**
 * IO和NIO文件操作
 * @author wing
 * @date 2012/7/22
 */
public class FileIO {
    private static final int count = 400000;
	private static final int bufferSize = 400000;
 
    /**
     * 不使用Buffer包装的输出流写入文件
     */
    public static void writeIO(String fileName){
    	DataOutputStream mDos = null;
    	try {
			mDos = new DataOutputStream(new FileOutputStream(new File(fileName)));
			for(int i = 0; i < count; i++){
				mDos.writeInt(1);
			}
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found:" + e.toString());
		} catch (IOException e) {
			System.out.println("IO Exception:" + e.toString());
		}finally{
		   if(mDos != null){
			try {
				mDos.close();
			} catch (IOException e) {
				System.out.println("Stream Close Exception:" + e.toString());
			}
		   }
		}
    }
    
    /**
     * 不使用Buffer包装输入流读入文件
     */ 
    public static void readIO(String fileName){
    	DataInputStream mDis = null;
    	try {
			mDis = new DataInputStream(new FileInputStream(new File(fileName)));
			for(int i = 0; i < count; i++){
				mDis.readInt();
			}
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found:" + e.toString());
		} catch (IOException e) {
			System.out.println("IO Exception:" + e.toString());
		}finally{
		   if(mDis != null){
			try {
				mDis.close();
			} catch (IOException e) {
				System.out.println("Stream Close Exception:" + e.toString());
			}
		   }
		}
    }
    
    /**
     * 使用Buffer包装的输出流写入文件
     */
    public static void writeIOWithBuffer(String fileName){
    	DataOutputStream mDos = null;
    	try {
			mDos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File(fileName))));
			for(int i = 0; i < count; i++){
				mDos.writeInt(1);
			}
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found:" + e.toString());
		} catch (IOException e) {
			System.out.println("IO Exception:" + e.toString());
		}finally{
		   if(mDos != null){
			try {
				mDos.close();
			} catch (IOException e) {
				System.out.println("Stream Close Exception:" + e.toString());
			}
		   }
		}
    }
    
    /**
     * 使用Buffer包装输入流读入文件
     */ 
    public static void readIOWithBuffer(String fileName){
    	DataInputStream mDis = null;
    	try {
			mDis = new DataInputStream(new BufferedInputStream(new FileInputStream(new File(fileName))));
			for(int i = 0; i < count; i++){
				mDis.readInt();
			}
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found:" + e.toString());
		} catch (IOException e) {
			System.out.println("IO Exception:" + e.toString());
		}finally{
		   if(mDis != null){
			try {
				mDis.close();
			} catch (IOException e) {
				System.out.println("Stream Close Exception:" + e.toString());
			}
		   }
		}
    }
    
    
    /**
     * 使用NIO管道来进行数据写入
     */
    public static void writeNIO(String fileName){
    	FileChannel mFc = null;
    	try {
			mFc = new FileOutputStream(new File(fileName)).getChannel();
			IntBuffer mBuffer = IntBuffer.allocate(bufferSize);
			for(int i = 0; i < count; i++){
				mBuffer.put(1);
			}
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found:" + e.toString());
		}finally{
		   if(mFc != null){
			try {
				mFc.close();
			} catch (IOException e) {
				System.out.println("Channel Close Exception:" + e.toString());
			}
		   }
		}
    }
    
    /**
     * 使用NIO管道来进行数据读取
     */ 
    public static void readNIO(String fileName){
    	FileChannel mFc = null;
    	try {
    		mFc = new FileInputStream(new File(fileName)).getChannel();
    		IntBuffer mBuffer = IntBuffer.allocate(bufferSize);
			for(int i = 0; i < count; i++){
				mBuffer.get();
			}		
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found:" + e.toString());
		}finally{
		   if(mFc != null){
			try {
				mFc.close();
			} catch (IOException e) {
				System.out.println("Channel Close Exception:" + e.toString());
			}
		   }
		}
    }
    
    /**
     * 使用NIO管道来进行数据写入
     */
    public static void writeNIOWithRan(String fileName){
    	FileChannel mFc = null;
    	try {
			mFc = new RandomAccessFile(fileName, "rw").getChannel();
			IntBuffer mBuffer = mFc.map(MapMode.READ_WRITE, 0, 4 * bufferSize).asIntBuffer();
			for(int i = 0; i < count; i++){
				mBuffer.put(1);
			}
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found:" + e.toString());
		} catch (IOException e) {
			System.out.println("IO Exception:" + e.toString());
		}finally{
		   if(mFc != null){
			try {
				mFc.close();
			} catch (IOException e) {
				System.out.println("Channel Close Exception:" + e.toString());
			}
		   }
		}
    }
    
    /**
     * 使用NIO管道来进行数据读取
     */ 
    public static void readNIOWithRan(String fileName){
    	FileChannel mFc = null;
    	try {
			mFc = new RandomAccessFile(fileName, "rw").getChannel();
			IntBuffer mBuffer = mFc.map(MapMode.READ_WRITE, 0, 4 * bufferSize).asIntBuffer();
			for(int i = 0; i < count; i++){
				mBuffer.get();
			}		
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found:" + e.toString());
		} catch (IOException e) {
			System.out.println("IO Exception:" + e.toString());
		}finally{
		   if(mFc != null){
			try {
				mFc.close();
			} catch (IOException e) {
				System.out.println("Channel Close Exception:" + e.toString());
			}
		   }
		}
    }  
}

大家可以看到,上面有各种IO的操作。操作次数是读写int类型400000次。


然后是我们的主类。


package org.wing.nio.test;

public class MainClass {

	public static void main(String[] args) {
		final String fileName = "test";
		TestIO[] testList = new TestIO[] { 
		   new TestIO() {

			@Override
			protected void test() {
				FileIO.writeIO(fileName);
			}
		}, new TestIO() {

			@Override
			protected void test() {
				FileIO.readIO(fileName);
			}
		}, new TestIO() {

			@Override
			protected void test() {
				FileIO.writeIOWithBuffer(fileName);
			}
		}, new TestIO() {

			@Override
			protected void test() {
				FileIO.readIOWithBuffer(fileName);
			}
		}, new TestIO() {

			@Override
			protected void test() {
				FileIO.writeNIO(fileName);
			}
		}, new TestIO() {

			@Override
			protected void test() {
				FileIO.readNIO(fileName);
			}
		},

		new TestIO() {

			@Override
			protected void test() {
				FileIO.writeNIOWithRan(fileName);

			}
		}, new TestIO() {

			@Override
			protected void test() {
				FileIO.readNIOWithRan(fileName);

			}
		},

		};
		
		for(TestIO testIO : testList){
			testIO.testTime();
		}

	}

}

新建了一个TestIO类的数组,分别重写test方法,使用自己的IO操作。然后循环执行TestIO的testTime方法。


运行程序,看看结果。


大家可以看到,在不使用Buffer装饰的IO操作中,进行400000次的int写操作耗时5.764秒,读操作3.301秒。而使用Buffer装饰的IO操作读0.021秒,写0.020秒。 但是直接使用nio的管道进行普通文件和随机读写文件的IO操作,耗时更小,写操作仅0.010秒,读操作仅0.006秒。


在第一次测试中,大家可以很明显的看出来,使用Buffer装饰的IO操作已经远远的超过了不使用Buffer装饰的IO操作的速度。而在400000次操作中与nio包的管道读写速度相差无几。


那么,io包跟nio包的IO读写速度就真的差不多么?

我们进行下一轮的测试。


注释掉,不使用Buffer装饰的TestIO类的创建,因为我们要增加IO操作次数了,不使用Buffer装饰的IO操作将会极为耗时。

我们将IO操作次数改为4000000次。

运行查看结果。



大家可以看到,在4000000次的IO操作中,buffer的普通IO操作读写耗时在0.6秒左右,而使用管道的IO操作,读写时间在0.05秒左右,使用随机访问文件的管道的IO操作读写时间在0.065秒左右。


那么,我们继续增加IO操作次数,增加到40000000次。

运行程序,看看结果。


大家可以看到,增加了IO操作次数之后,io包里带buffer的IO操作,写操作耗时达到了5.8秒,而读操作达到了1.7秒!!但是使用nio包管道的IO操作,写操作耗时仅0.33秒,读操作耗时仅0.27秒。使用随机访问文件的管道的IO操作耗时略微高一点,写操作0.57秒,读操作0.4秒。


由此可以看出,即使在jdk 1.4之后重写了io包,提升了效率。但是在达到一定的IO次数之后,io包与nio包管道操作的效率的差距已经越来越大了。而使用随机访问文件的普通IO操作,虽然耗时略高一点,但整体不受太大影响。不过我这里没进行seek操作,然后读写。估计还是会影响比较大的效率。


当然,在我们日常开发中,使用io包的装饰buffer的IO操作已经够用了。不过这也从另外一方面显示出了nio包的强大与高效。


测试可能有很多地方不正确,但整体应该没有很大的问题,大家看看即可。

转载请注明出处:http://blog.csdn.net/ml3947

分享到:
评论

相关推荐

    java nio与io性能测试

    本文将深入探讨Java NIO与IO的性能测试,并通过代码实例来展示它们之间的差异。 首先,我们来看传统的Java IO模型。IO模型基于流,数据是从输入流到输出流的单向传输。例如,`FileInputStream`和`FileOutputStream`...

    Java NIO与IO性能对比分析.pdf

    本文将分析Java NIO与Java IO在性能上的对比,并尝试找出性能差异的原因,以及探讨哪种编程模型更适合高并发的应用场景。 Java IO模型是一种阻塞型I/O模型,在数据的读写过程中,如果线程在等待数据,将会一直被挂...

    利用缓冲区提高Java应用程序的IO性能

    ### 利用缓冲区提高Java应用程序的IO性能 #### 摘要与背景介绍 Java作为一门具有跨平台特性的编程语言,在多个领域都获得了广泛的应用。随着Java应用的不断扩展,其性能问题逐渐成为人们关注的重点,尤其是输入...

    推荐一款好用的JAVA IO分析工具JPicus

    标题中的“JPicus”是一款专为Java IO...对于任何处理大量数据或对IO性能有高要求的Java应用,JPicus都是一款值得推荐的工具。通过深入学习和使用,开发者可以更好地理解和优化他们的IO操作,从而提高整个系统的效率。

    Javaio流思维导图

    还有FileChannel和Selector等NIO(非阻塞I/O)组件,它们在高并发场景下提高了性能,通过选择器可以选择多个通道进行读写,而无需轮询。 最后,别忘了关闭流的重要性。每当完成I/O操作后,都应调用close()方法释放...

    JAVA IO and NIO

    在IntelliJ IDEA中,开发者可以方便地使用Java IO和NIO编写和测试相关的代码。IDE提供了强大的代码补全、调试和测试工具,使得开发过程更加高效。对于Java IO,IntelliJ IDEA会自动处理流的关闭,对于NIO,它也提供...

    JAVA IO 输入输出处理.ppt

    Java IO 输入输出处理是Java编程中至关重要的一部分,用于在程序和外部资源(如磁盘、网络、内存等)之间传输数据。Java的IO系统由java.io包提供,它包含了一系列的类和接口,用于实现不同类型的输入输出操作。 **...

    java的各种io操作

    Java的IO操作是Java编程中的重要组成部分,它允许开发者处理输入和输出,包括读取文件、写入...同时,随着Java NIO(New IO)和NIO.2的引入,Java的IO性能和功能得到了显著提升,为开发者提供了更多高效和灵活的选择。

    java服务程序性能测试总结

    【Java服务程序性能测试总结】 在软件开发过程中,性能测试是一项至关重要的环节,尤其是在Java服务程序的场景下,确保服务程序能承受高并发负载并保持高效稳定运行是开发者的重要任务。以下是对整个性能测试过程的...

    java io一些探讨

    针对不同大小的文件进行了读写性能测试: - **文件大小为 2K** - **文件大小为 10K** - **文件大小为 100K** - **文件大小为 1M** - **文件大小为 10M** **6. 结论** - 对于小文件,使用`BufferedReader`和`...

    利用java的IO流写的一个记事本

    Java的IO流是Java平台核心特性之一,它用于在程序与外部资源(如磁盘、网络、内存等)之间传输数据。在这个项目中,“利用Java的IO流写的一个记事本”是一个用Java编程语言实现的简单文本编辑器,具备基本的新建文件...

    javaIO流基础.zip_IO流 上传 下载文件_io流 上传_io流下载_下载

    在这个“javaIO流基础.zip”压缩包中,我们能看到一系列与文件上传和下载相关的Java代码示例,涵盖了多种IO流类型及其用法。 首先,`TestFileOutputStream.java`和`TestFileInputStream.java`涉及到的是文件输入流...

    java IO流方式上传下载文件,源代码

    本篇文章将深入探讨如何使用Java IO流实现文件的上传和下载功能,以及两个已测试通过的JSP程序——`uploadDRFile.jsp`和`daoRuform.jsp`的应用。 1. **文件上传**: 文件上传通常发生在用户通过网页表单选择本地...

    Java IO流操作

    Java IO流操作是Java编程语言中的重要组成部分,它允许程序进行输入输出操作...在IOTest这个例子中,我们可以创建测试类来实践各种流的使用,如文件的读写、缓冲区的运用、对象的序列化等,进一步巩固对Java IO的理解。

    JAVA 的IO流的文件复制

    在Java编程语言中,IO(Input/Output)流是处理数据输入和输出的重要工具,尤其在文件操作中显得尤为重要。本篇文章将详细讲解如何使用Java的IO流进行文件复制,以及如何实现整个文件夹的复制,并检查复制是否成功。...

    Java IO流的相关操作

    Java IO流是Java平台中用于处理输入输出的重要机制,它允许程序与各种设备(如硬盘、内存、网络连接等)进行数据传输。在Java中,IO流被设计为面向对象的,提供了丰富的类库来支持各种类型的数据传输,包括字符流、...

    Java io输入输出流及字符集

    Java提供Charset类来处理字符集,它可以用来获取已知的字符集、检测编码、解码等。 三、管道流和对象流 1. 管道流(PipedStream) 管道流允许线程间通信,如PipedInputStream和PipedOutputStream,一个线程写入,另...

    eclipse开发性能优化、java代码性能优化

    ### Eclipse 开发性能优化与 Java 代码性能优化 在日常的软件开发过程中,尤其是在使用 Eclipse 进行 Android 开发时,经常会遇到 IDE 运行缓慢的情况。为了提高开发效率,本文将详细介绍 Eclipse 开发环境及 Java ...

    java性能优化教程

    最后,持续的代码审查和性能测试至关重要。编写基准测试,通过JMH(Java Microbenchmark Harness)进行微基准测试,确保优化措施有效且不会引入新的问题。 总的来说,Java性能优化涉及代码质量、JVM配置、并发处理...

    java(IO)第二部分

    Java NIO(New IO)是自Java 1.4引入的一个重要扩展,它提供了非阻塞I/O和选择器等特性,提高了I/O性能和可伸缩性。通道(Channel)和缓冲区(Buffer)是NIO的核心概念,而Selector允许单个线程同时处理多个连接。 ...

Global site tag (gtag.js) - Google Analytics