`
webcode
  • 浏览: 5954791 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

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性能测试

    NULL 博文链接:https://ilrxx.iteye.com/blog/1051402

    java-虚拟机 操作系统监控工具-源码

    适合用于服务健康监控、线上调优、排查问题、性能测试等场景 支持操作系统监控:内存状态、CPU负载、磁盘IO及吞吐率、磁盘健康状态、网卡信息、网卡IO 支持Java虚拟机监控:GC信息、内存使用情况、内存池信息、类...

    高性能IO模型浅析

    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型。 (2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置...

    xio:适用于Java 8的高性能多线程异步IO

    状态io 适用于Java 8的高性能多线程非阻塞异步I / O Simplicity Leads to Purity - Jiro Xio是用于构建高性能,可扩展网络应用程序的网络库完整的自述文件和文档即将推出,以查看示例用法,并测试一下。使用代码库...

    Java性能调优实战——覆盖80%以上的Java应用调优场景

    开篇词讲怎样才能做好性能调优02讲如何制定性能调优策略04讲...索引的失效与优化36讲什么时候需要分表分库37讲电商系统表设计优化案例分析39讲答疑课堂:MySQL中InnoDB的知识点串讲加餐讲推荐几款常用的性能测试工具

    java源码包---java 源码 大量 实例

     Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...

    JAVA上百实例源码以及开源项目源代码

     Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...

    JAVA上百实例源码以及开源项目

     Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...

    Java计算文件MD5值(支持大文件)

    import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.MessageDigest; import org.apache.commons.codec.binary.Hex; import org.apache.commons....

    java开源包4

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包11

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包6

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包101

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包9

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    Java项目如何进行性能优化

    2,压力测试&调优 内容导语: 01-性能优化的终极目标是什么? 用户体验 = 产品设计(非技术) + 系统性能 ≈ 系统性能 = 快? 应用性能是产品用户体验的基石,性能优化的终极目标是优化用户体验。当我们谈及性能,最...

    java开源包5

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    iotester:用于分析网络或文件系统的 IO 性能的 Java 测试工具

    一个独立的 Java 实用程序,用于测试网络上一组机器的网络 (TCP) 和磁盘输入/输出性能(即不太了解的云环境)。 需要安装 Java 1.6+ 和 Make。 构建: 制作 运行 jar 会打印一个解释参数的用法声明。 运行一段...

    java开源包8

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java开源包10

    Tomcat Native 这个项目可以让 Tomcat 使用 Apache 的 apr 包来处理包括文件和网络IO操作,以提升性能。 预输入搜索 Cleo Cleo 是一个灵活的软件库用于处理一些预输入和自动完成的搜索功能,该项目是 LinkedIn 公司...

    java源码包2

     Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码...

Global site tag (gtag.js) - Google Analytics