首頁>技術>

前言

直接記憶體大多時候也被稱為堆外記憶體,自從 JDK 引入 NIO 後,直接記憶體的使用也越來越普遍。透過 native 方法可以分配堆外記憶體,透過 DirectByteBuffer 物件來操作。

直接記憶體不屬於 Java 堆,所以它不受堆大小限制,但是它受物理記憶體大小的限制。

配置

可以透過 -XX:MaxDirectMemorySize 引數來設定最大可用直接記憶體,如果啟動時未設定則預設為最大堆記憶體大小,即與 -Xmx 相同。即假如最大堆記憶體為1G,則預設直接記憶體也為1G,那麼 JVM 最大需要的記憶體大小為2G多一些。當直接記憶體達到最大限制時就會觸發GC,如果回收失敗則會引起OutOfMemoryError。

分配記憶體耗時

環境為JDK9,兩種記憶體分配的耗時如下,執行兩遍讓其預熱。可以看到直接記憶體的分配比較耗時,而堆記憶體分配操作耗時少好幾倍。

public static void directMemoryAllocate() {        long tsStart = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            ByteBuffer buffer = ByteBuffer.allocateDirect(400);        }        System.out.println("direct memory allocate: " + (System.currentTimeMillis() - tsStart) + " ms");        tsStart = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            ByteBuffer buffer = ByteBuffer.allocate(400);        }        System.out.println("heap memory allocate: " + (System.currentTimeMillis() - tsStart) + " ms");    }
direct memory allocate: 149 msheap memory allocate: 41 msdirect memory allocate: 122 msheap memory allocate: 31 ms
讀寫操作耗時

環境為JDK9,兩種記憶體的讀寫操作耗時如下,同樣執行兩遍讓其預熱,可以看到直接記憶體讀寫操作的速度相對快一些。

public static void memoryRW() {        ByteBuffer buffer = ByteBuffer.allocateDirect(400);        ByteBuffer buffer2 = ByteBuffer.allocate(400);        long tsStart = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            for (int j = 0; j < 100; j++) {                buffer.putInt(j);            }            buffer.flip();            for (byte j = 0; j < 100; j++) {                buffer.getInt();            }            buffer.clear();        }        System.out.println("direct memory rw: " + (System.currentTimeMillis() - tsStart) + " ms");        tsStart = System.currentTimeMillis();        for (int i = 0; i < 100000; i++) {            for (int j = 0; j < 100; j++) {                buffer2.putInt(j);            }            buffer2.flip();            for (byte j = 0; j < 100; j++) {                buffer2.getInt();            }            buffer2.clear();        }        System.out.println("heap memory rw: " + (System.currentTimeMillis() - tsStart) + " ms");    }
direct memory rw: 39 msheap memory rw: 34 msdirect memory rw: 23 msheap memory rw: 46 ms
總結

理論上直接記憶體的機制訪問速度要快一些,但也不能武斷地直接說直接記憶體快,另外,在記憶體分配操作上直接記憶體要慢一些。直接記憶體更適合在記憶體申請次數較少,但讀寫操作較頻繁的場景。

11
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 前端工程師都會遇到的nodejs常見問題和解決方案覆盤