簡體   English   中英

為什么mmap()(內存映射文件)比read()更快

[英]Why mmap() (Memory Mapped File) is faster than read()

我最近正在研究Java NIO的MappedByteBuffer。 我已經閱讀了一些關於它的帖子,所有人都提到“mmap()比read()更快”

在我的結論中:

  1. 我對待MappedByteBuffer == Memory Mapped File == mmap()

  2. read()必須通過以下方式讀取數據:磁盤文件 - >內核 - >應用程序,因此它具有上下文切換和緩沖區復制

  3. 他們都說mmap()比read()具有更少的復制或系統調用,但據我所知,它還需要在您第一次訪問文件數據時從磁盤文件中讀取。 所以第一次讀它:虛擬地址 - >內存 - >頁面錯誤 - >磁盤文件 - >內核 - >內存。 除了你可以隨機訪問它,最后3個步驟(磁盤文件 - >內核 - >內存)與read()完全相同,那么mmap()如何比read()更少復制或系統調用?

  4. mmap()和交換文件之間的關系是什么,os是否會將最少使用的內存文件數據放入交換(LRU)? 因此,當您第二次訪問這些數據時,操作系統會從交換但不是磁盤文件中檢索它們(不需要復制到內核緩沖區),這就是為什么mmap()復制和系統調用較少的原因?

  5. 在java中,MappedByteBuffer是從堆中分配的(它是一個直接緩沖區)。 所以當你從MappedByteBuffer中讀取時,是否意味着它需要從Java堆外部再添加一個額外的內存副本到java堆中?

誰能回答我的問題? 謝謝 :)

1:是的,這基本上就是MappedByteBuffer。

2:“磁盤文件 - >內核”不一定涉及復制。

3:使用內存映射文件,一旦內核將文件讀入其緩存,它就可以簡單地將緩存的那部分映射到您的進程中 - 而不必將數據從緩存復制到您的進程指定的位置。

4:如果內核決定從內存映射文件中換出頁面,它將不會將頁面寫入頁面文件; 在丟棄頁面之前,它會將頁面寫入原始文件(從中映射的文件)。 將其寫入頁面文件將是不必要的並浪費頁面文件空間。

5:是的。 例如,如果調用get(byte[])則數據將從堆外映射復制到數組中。 請注意,諸如get(byte[])函數需要復制任何類型緩沖區的數據 - 這不是特定於內存映射文件的。

你在比較蘋果和橘子。 mmap() '比read()更快,因為它不執行任何I / O. 當您訪問由映射產生的內存地址時,I / O將延遲到。 I / O是一樣一樣read(),並且不管 I / O快於read()是一個很有爭議的問題。 在我接受之前,我希望看到一個合適的基准。

我對待MappedByteBuffer == Memory Mapped File == mmap()

好。

read()必須通過以下方式讀取數據:磁盤文件 - >內核 - >應用程序,因此它有兩次上下文切換和緩沖區復制

相比什么?

他們都說mmap()比read(),有更少的復制或系統調用read(),

它具有較少的系統調用。 它是否具有較少的復制取決於實現。 當然可以通過DMA直接讀取和寫入數據,但特定的操作系統是否是特定於操作系統的。

但據我所知,它還需要在您第一次訪問文件數據時從磁盤文件中讀取。

正確。

所以第一次讀它:虛擬地址 - >內存 - >頁面錯誤 - >磁盤文件 - >內核 - >內存。 除了你可以隨機訪問它,最后3個步驟(磁盤文件 - >內核 - >內存)與read()完全相同,那么mmap()如何比read()更少復制或系統調用?

因為DMA,如果實現的話。

mmap()和交換文件之間的關系是什么

分配給映射的內存是進程地址空間的一部分,它是虛擬的,並且需要進行交換,並且交換文件中必須有空間,就像任何其他內存一樣。

是os將把最少使用的內存文件數據放入交換(LRU)?

沒有。

因此,當您第二次訪問這些數據時,操作系統會從交換但不是磁盤文件中檢索它們(不需要復制到內核緩沖區),這就是為什么mmap()復制和系統調用較少的原因?

不。做所有這些都是錯的。

在java中, MappedByteBuffer是從堆中分配的(它是一個直接緩沖區)。

這沒有意義。 直接緩沖區不會從堆中分配,它們由mmap()或平台API分配,作為內存。 不在堆中。 MappedByteBuffer是直接緩沖區是正確的。

所以當你從MappedByteBuffer中讀取時,是否意味着它需要從Java堆外部再添加一個額外的內存副本到java堆中?

是的,但不是出於上述原因。 原因是你必須調用MappedByteBuffer.get()/put(),這本身就是一個額外的步驟。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM