Java IO效能測試

來源:互聯網
上載者:User

  在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() {@Overrideprotected void test() {FileIO.writeIO(fileName);}}, new TestIO() {@Overrideprotected void test() {FileIO.readIO(fileName);}}, new TestIO() {@Overrideprotected void test() {FileIO.writeIOWithBuffer(fileName);}}, new TestIO() {@Overrideprotected void test() {FileIO.readIOWithBuffer(fileName);}}, new TestIO() {@Overrideprotected void test() {FileIO.writeNIO(fileName);}}, new TestIO() {@Overrideprotected void test() {FileIO.readNIO(fileName);}},new TestIO() {@Overrideprotected void test() {FileIO.writeNIOWithRan(fileName);}}, new TestIO() {@Overrideprotected 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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.