1. 程式人生 > >Java直接記憶體與堆記憶體

Java直接記憶體與堆記憶體

NIO的Buffer提供了一個可以不經過JVM記憶體直接訪問系統實體記憶體的類——DirectBuffer。 DirectBuffer類繼承自ByteBuffer,但和普通的ByteBuffer不同,普通的ByteBuffer仍在JVM堆上分配記憶體,其最大記憶體受到最大堆記憶體的限制;而DirectBuffer直接分配在實體記憶體中,並不佔用堆空間,其可申請的最大記憶體受作業系統限制。

直接記憶體的讀寫操作比普通Buffer快,但它的建立、銷燬比普通Buffer慢。

因此直接記憶體使用於需要大記憶體空間且頻繁訪問的場合,不適用於頻繁申請釋放記憶體的場合。

 

(Note:DirectBuffer並沒有真正向OS申請分配記憶體,其最終還是通過呼叫Unsafe的allocateMemory()來進行記憶體分配。不過JVM對Direct Memory可申請的大小也有限制,可用-XX:MaxDirectMemorySize=1M設定,這部分記憶體不受JVM垃圾回收管理。)

以下是一些測試:

程式碼:

複製程式碼

 1 class DirectMemory {
 2 
 3     // 分配堆記憶體
 4     public static void bufferAccess() {
 5         long startTime = System.currentTimeMillis();
 6         ByteBuffer b = ByteBuffer.allocate(500);
 7         for (int i = 0; i < 1000000; i++) {
 8             for (int j = 0; j < 99; j++)
 9                 b.putInt(j);
10             b.flip();
11             for (int j = 0; j < 99; j++)
12                 b.getInt();
13             b.clear();
14         }
15         long endTime = System.currentTimeMillis();
16         System.out.println("access_nondirect:" + (endTime - startTime));
17     }
18 
19     // 直接分配記憶體
20     public static void directAccess() {
21         long startTime = System.currentTimeMillis();
22         ByteBuffer b = ByteBuffer.allocateDirect(500);
23         for (int i = 0; i < 1000000; i++) {
24             for (int j = 0; j < 99; j++)
25                 b.putInt(j);
26             b.flip();
27             for (int j = 0; j < 99; j++)
28                 b.getInt();
29             b.clear();
30         }
31         long endTime = System.currentTimeMillis();
32         System.out.println("access_direct:" + (endTime - startTime));
33     }
34 
35     public static void bufferAllocate() {
36         long startTime = System.currentTimeMillis();
37         for (int i = 0; i < 1000000; i++) {
38             ByteBuffer.allocate(1000);
39         }
40         long endTime = System.currentTimeMillis();
41         System.out.println("allocate_nondirect:" + (endTime - startTime));
42     }
43 
44     public static void directAllocate() {
45         long startTime = System.currentTimeMillis();
46         for (int i = 0; i < 1000000; i++) {
47             ByteBuffer.allocateDirect(1000);
48         }
49         long endTime = System.currentTimeMillis();
50         System.out.println("allocate_direct:" + (endTime - startTime));
51     }
52 
53     public static void main(String args[]) {
54         System.out.println("訪問效能測試:");
55         bufferAccess();
56         directAccess();
57 
58         System.out.println();
59 
60         System.out.println("分配效能測試:");
61         bufferAllocate();
62         directAllocate();
63     }
64 }

複製程式碼

結果:

複製程式碼

訪問效能測試:
access_nondirect:157
access_direct:134

分配效能測試:
allocate_nondirect:231
allocate_direct:613

複製程式碼

可見與在JVM堆分配記憶體(allocate)相比,直接記憶體分配(allocateDirect)的訪問效能更好,但分配較慢。(一般如此,當然資料量小的話差別不是那麼明顯)

 

from: https://www.cnblogs.com/z-sm/p/6235157.html