1. 程式人生 > >java IO和NIO效能比較

java IO和NIO效能比較

學習了java nio原理,一直停留在理論的階段,今天就來對java中的IO和NIO效能做個測試,測試程式碼主要通過堆記憶體、直接記憶體和記憶體對映讀取一個88M的檔案,測試程式碼如下,剛開始緩衝大小都是1KB,後面改為檔案大小(88MB)。

public class IOTest 
{
	//讀取的檔案,大小為88M
	static private File file = new File("D://1.pdf");
	//緩衝大小1024位元組
	static private final int BUFFER_SIZE = 1024;
	//記憶體對映檔案
	public static void MapTest() throws Exception
	{
		FileInputStream in = new FileInputStream(file);  
        FileChannel channel = in.getChannel();  
        //分配88M的直接記憶體
        MappedByteBuffer buff = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
        byte[] b = new byte[1024];  
        int len = (int) file.length();  
        
        
        long begin = System.currentTimeMillis(); 
        
        for (int offset = 0; offset < len; offset += 1024) 
        {  
            if (len - offset > BUFFER_SIZE) 
            {  
                buff.get(b);  
            } 
            else 
            {  
                buff.get(new byte[len - offset]);  
            }  
        }  
        
        long end = System.currentTimeMillis();  
	    System.out.println("map time is:" + (end - begin) + "ms");  
	}
	//直接記憶體
	public static void DirectTest() throws Exception
	{
		FileInputStream in = new FileInputStream(file);  
		FileChannel channel = in.getChannel();
		//分配1KB直接記憶體
		ByteBuffer buff = ByteBuffer.allocateDirect(BUFFER_SIZE);
		  
		long begin = System.currentTimeMillis(); 
		
		while (channel.read(buff) != -1) 
		{  
		    buff.flip();  
		    buff.clear();  
		}  
		
		long end = System.currentTimeMillis();  
	    System.out.println("Direct time is:" + (end - begin) + "ms");  
	}
	//堆記憶體
	public static void HeapTest() throws Exception
	{
		FileInputStream in = new FileInputStream(file);  
		FileChannel channel = in.getChannel();  
		ByteBuffer buff = ByteBuffer.allocate(BUFFER_SIZE);//分配1KB堆記憶體   
		  
		long begin = System.currentTimeMillis(); 
		
		while (channel.read(buff) != -1) 
		{  
		    buff.flip();  
		    buff.clear();  
		}   
		
		long end = System.currentTimeMillis();  
	    System.out.println("heap time is:" + (end - begin) + "ms");  
	}
	
	public static void main(String[] args) throws Exception
	{	 	
		MapTest();
		DirectTest();
		HeapTest();
	}
}

程式輸出結果:

記憶體對映檔案方式:52ms

緩衝區1KB大小 緩衝區檔案大小(88M)
直接記憶體方式:904ms 89ms
堆記憶體方式:991ms 270ms

測試結果效能顯示:記憶體對映檔案方式>直接記憶體方式>堆記憶體方式

這是因為JVM在讀取資料的時候涉及到堆記憶體、直接記憶體、核心記憶體、磁碟。堆記憶體方式讀取資料首先將資料從磁碟讀取到核心記憶體,再從核心記憶體拷貝到直接記憶體,最後從直接記憶體拷貝到堆記憶體,應用程式就可以使用這些資料。記憶體對映檔案方式和直接記憶體方式都是將資料儲存到直接記憶體中,並且記憶體對映方式可以繞過核心記憶體而直接將磁碟的資料讀取到直接記憶體中。