直接記憶體和堆記憶體誰快

超人汪小建發表於2018-05-30

前言

直接記憶體大多時候也被稱為堆外記憶體,自從 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 ms
heap memory allocate: 41 ms
direct memory allocate: 122 ms
heap 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 ms
heap memory rw: 34 ms
direct memory rw: 23 ms
heap memory rw: 46 ms
複製程式碼

總結

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

-------------推薦閱讀------------

我的2017文章彙總——機器學習篇

我的2017文章彙總——Java及中介軟體

我的2017文章彙總——深度學習篇

我的2017文章彙總——JDK原始碼篇

我的2017文章彙總——自然語言處理篇

我的2017文章彙總——Java併發篇


跟我交流,向我提問:

這裡寫圖片描述

公眾號的選單已分為“讀書總結”、“分散式”、“機器學習”、“深度學習”、“NLP”、“Java深度”、“Java併發核心”、“JDK原始碼”、“Tomcat核心”等,可能有一款適合你的胃口。

為什麼寫《Tomcat核心設計剖析》

歡迎關注:

這裡寫圖片描述

相關文章