MappedByteBuffer

計算機內存管理

原文連接 http://www.javashuo.com/article/p-qzifpasi-ky.html
MMC:CPU的內存管理單元。
物理內存:即內存條的內存空間。
虛擬內存:計算機系統內存管理的一種技術。它使得應用程序認爲它擁有連續的可用的內存(一個連續完整的地址空間),而實際上,它一般是被分隔成多個物理內存碎片,還有部分暫時存儲在外部磁盤存儲器上,在須要時進行數據交換。
頁面文件:操做系統反映構建並使用虛擬內存的硬盤空間大小而建立的文件,在windows下,即pagefile.sys文件,其存在乎味着物理內存被佔滿後,將暫時不用的數據移動到硬盤上。
缺頁中斷:當程序試圖訪問已映射在虛擬地址空間中但未被加載至物理內存的一個分頁時,由MMC發出的中斷。若是操做系統判斷這次訪問是有效的,則嘗試將相關的頁從虛擬內存文件中載入物理內存。html

MappedByteBuffer介紹

MappedByteBuffer 是Java NIO中引入的一種硬盤物理文件和內存映射方式,當物理文件較大時,採用MappedByteBuffer,讀寫性能較高,其內部的核心實現是DirectByteBuffer(JVM 堆外直接物理內存)。java

JVM 進程經過內存映射方式加載的物理文件並不會耗費同等大小的物理內存。當應用程序訪問數據時,程序經過虛擬地址尋址對應的內存頁,若是物理內存中不存在對應頁,MMU則會產生缺頁中斷異常,CPU嘗試從系統Swap分區中查找,如仍不存在,則會直接從硬盤中物理文件中讀取。windows

傳統的基於文件流的方式讀取文件方式是系統指令調用,文件數據首先會被讀取到進程的內核空間的緩衝區,然後複製到進程的用戶空間,這個過程當中存在兩次數據拷貝;而內存映射方式讀取文件的方式,也是系統指令調用,在產生缺頁中斷後,CPU直接從磁盤文件load數據到進程的用戶空間,只有一次數據拷貝。api

FileChannel提供了map方法把磁盤文件映射到虛擬內存,一般狀況能夠映射整個文件,若是文件比較大,能夠進行分段映射。app

內存映像文件訪問的方式,共三種:性能

a) MapMode.READ_ONLY:只讀,試圖修改獲得的緩衝區將致使拋出異常。

    b) MapMode.READ_WRITE:讀/寫,對獲得的緩衝區的更改最終將寫入文件;但該更改對映射到同一文件的其餘程序不必定是可見的。

    c) MapMode.PRIVATE:私用,可讀可寫,可是修改的內容不會寫入文件,只是buffer自身的改變。

MappedByteBuffer在處理大文件時的確性能很高,但也存在一些問題,其所對應的內存使用的是JVM堆外內存,JVM young gc和CMS gc並不能觸發回收MappedByteBuffer對應的內存,只有full gc(stop the world的方式)可使其回收內存,堆外直接內存會根據本身的狀況(當須要新分配直接內存時,若是所剩堆外內存空間不夠,第一次產生OutOfMemoryError時)來觸發 System.gc(),此處有坑,若JVM配置了參數-XX:DisableExplicitGC,System.gc()將不會觸發full gc,最終致使內存泄漏。並且觸發其內存回收的時間點是不肯定的。Java api文檔中標註:操作系統

A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.code

在應用程序頻繁使用堆外內存時,還能夠經過-XX:MaxDirectMemorySize來指定最大的堆外內存大小,當使用達到了閾值的時候將調用System.gc來作一次full gc,以此來回收掉遊離狀態的堆外內存。
所以,在使用堆外內存高性能的福利的同時,及時的回收掉廢棄掉的內存是十分關鍵的。htm

性能分析
從代碼層面上看,從硬盤上將文件讀入內存,都要通過文件系統進行數據拷貝,而且數據拷貝操做是由文件系統和硬件驅動實現的,理論上來講,拷貝數據的效率是同樣的。
可是經過內存映射的方法訪問硬盤上的文件,效率要比read和write系統調用高,這是爲何?blog

read()是系統調用,首先將文件從硬盤拷貝到內核空間的一個緩衝區,再將這些數據拷貝到用戶空間,實際上進行了兩次數據拷貝;
map()也是系統調用,但沒有進行數據拷貝,當缺頁中斷髮生時,直接將文件從硬盤拷貝到用戶空間,只進行了一次數據拷貝。
因此,採用內存映射的讀寫效率要比傳統的read/write性能高。

總結
MappedByteBuffer使用虛擬內存,所以分配(map)的內存大小不受JVM的-Xmx參數限制,可是也是有大小限制的。
若是當文件超出1.5G限制時,能夠經過position參數從新map文件後面的內容。
MappedByteBuffer在處理大文件時的確性能很高,但也存在一些問題,如內存佔用、文件關閉不肯定,被其打開的文件只有在垃圾回收的纔會被關閉,並且這個時間點是不肯定的。
javadoc中也提到:A mapped byte buffer and the file mapping that it represents remain* valid until the buffer itself is garbage-collected.
原文連接 http://www.javashuo.com/article/p-qzifpasi-ky.html

相關文章
相關標籤/搜索