天天看點

Java直接記憶體與非直接記憶體性能測試

什麼是直接記憶體與非直接記憶體

根據官方文檔的描述:

A byte buffer is either direct or non-direct. Given a direct byte buffer, the Java virtual machine will make a best effort to perform native I/O operations directly upon it. That is, it will attempt to avoid copying the buffer's content to (or from) an intermediate buffer before (or after) each invocation of one of the underlying operating system's native I/O operations.
           

byte byffer

可以是兩種類型,一種是基于直接記憶體(也就是非堆記憶體);另一種是非直接記憶體(也就是堆記憶體)。

對于直接記憶體來說,JVM将會在IO操作上具有更高的性能,因為它直接作用于本地系統的IO操作。而非直接記憶體,也就是堆記憶體中的資料,如果要作IO操作,會先複制到直接記憶體,再利用本地IO處理。

從資料流的角度,非直接記憶體是下面這樣的作用鍊:

本地IO-->直接記憶體-->非直接記憶體-->直接記憶體-->本地IO
           

而直接記憶體是:

本地IO-->直接記憶體-->本地IO
           

很明顯,再做IO處理時,比如網絡發送大量資料時,直接記憶體會具有更高的效率。

A direct byte buffer may be created by invoking the allocateDirect factory method of this class. The buffers returned by this method typically have somewhat higher allocation and deallocation costs than non-direct buffers. The contents of direct buffers may reside outside of the normal garbage-collected heap, and so their impact upon the memory footprint of an application might not be obvious. It is therefore recommended that direct buffers be allocated primarily for large, long-lived buffers that are subject to the underlying system's native I/O operations. In general it is best to allocate direct buffers only when they yield a measureable gain in program performance.
           

但是,不要高興的太早。文檔中也說了,直接記憶體使用allocateDirect建立,但是它比申請普通的堆記憶體需要耗費更高的性能。不過,這部分的資料是在JVM之外的,是以它不會占用應用的記憶體。

是以呢,當你有很大的資料要緩存,并且它的生命周期又很長,那麼就比較适合使用直接記憶體。隻是一般來說,如果不是能帶來很明顯的性能提升,還是推薦直接使用堆記憶體。

關于直接記憶體需要注意的,就是上面兩點了,其他的關于視圖啊、作用鍊啊,都是使用上的問題了。如果有興趣,可以 參考官方API ( 進去後搜尋ByteBuffer,就能看到!),裡面有少量的描述!重要的一些用法,還得自己摸索。

使用場景

通過上面的官方文檔,與一些資料的搜尋。可以總結下,直接記憶體的使用場景:

  • 1 有很大的資料需要存儲,它的生命周期又很長
  • 2 适合頻繁的IO操作,比如網絡并發場景

申請配置設定位址速度比較

下面用一段簡單的代碼,測試下申請記憶體空間的速度:

int time = 10000000;
Date begin = new Date();
for(int i=0;i<time;i++){
	ByteBuffer buffer = ByteBuffer.allocate(2);
}
Date end = new Date();
System.out.println(end.getTime()-begin.getTime());
begin = new Date();
for(int i=0;i<time;i++){
	ByteBuffer buffer = ByteBuffer.allocateDirect(2);
}
end = new Date();
System.out.println(end.getTime()-begin.getTime());
           

得到的測試結果如下:

Java直接記憶體與非直接記憶體性能測試

在資料量提升時,直接記憶體相比于非直接記憶體的申請 有十分十分十分明顯的性能問題!

讀寫速度比較

然後在寫段代碼,測試下讀寫的速度:

int time = 1000;
Date begin = new Date();
ByteBuffer buffer = ByteBuffer.allocate(2*time);
for(int i=0;i<time;i++){
	buffer.putChar('a');
}
buffer.flip();
for(int i=0;i<time;i++){
	buffer.getChar();
}
Date end = new Date();
System.out.println(end.getTime()-begin.getTime());
begin = new Date();
ByteBuffer buffer2 = ByteBuffer.allocateDirect(2*time);
for(int i=0;i<time;i++){
	buffer2.putChar('a');
}
buffer2.flip();
for(int i=0;i<time;i++){
	buffer2.getChar();
}
end = new Date();
System.out.println(end.getTime()-begin.getTime());
           

測試的結果如下:

Java直接記憶體與非直接記憶體性能測試

可以看到直接記憶體在直接的IO操作上,還是有明顯的差異的!

作者:xingoo

出處:http://www.cnblogs.com/xing901022

本文版權歸作者和部落格園共有。歡迎轉載,但必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接!