簡體   English   中英

mmap如何提高文件讀取速度?

[英]How does mmap improve file reading speed?

假設地址空間可以覆蓋文件,在我看來mmap只是分配一塊與要讀取的文件一樣大的內存塊,並在它們相應的塊之間創建一對一的關系。 但是,為什么這樣做會加快文件讀取速度? 似乎為了實際獲取文件的內容,您仍然必須轉到磁盤,並讀取它上面的所有字節。

與malloc相同大小的內存並手動將整個文件讀入malloc區域相比,它有何不同?

mmap工作方式不同。 這是預期的,並適應該計划的訪問模式。 此外,可以通過madvise設置特定策略以進一步微調使用。

有關mmap如何在請求分頁環境中工作的更全面的討論,請參閱我的答案: 哪些段受寫入時復制的影響? 因為它還討論了使用mmap

mmapexecve等程序執行的命脈。 人。 所以,你可以打賭它很快。 作為旁注,具有諷刺意味的是, malloc實際上也使用了匿名mmap

但是,特別要在這里進行討論,請注意mmap與執行mallocread(2)的文件的“后備存儲”(即分頁磁盤read(2)

使用mmap ,內存區域的后備存儲是文件本身。 該區域將頁面直接映射到內核的文件系統緩沖區頁面[它們已經統一了很長時間]。 因此,與read(2) ,不需要從內核文件系統緩沖區頁面到應用程序頁面的[浪費]副本。

當您執行malloc/read ,您仍然擁有上述頁面,但是,現在malloc/read區域在分頁/交換磁盤上有一個后備存儲。 因此,頁面緩沖區的數量是mmap 兩倍 正如我所提到的,讀取完成后必須將數據復制到該區域。

此外,在性能方面,進行大量讀取是次優的。 塊[文件系統相關]中的建議大小約為64 KB。

執行大型讀取時,程序在完成之前無法啟動。 如果文件的大小大於物理內存,系統將讀入您的malloc區域,並浪費地將早期頁面刷新到分頁磁盤,為文件末尾附近的頁面騰出空間,直到整個文件為止。讀入。

換句話說,當這個大的預讀發生時,應用程序正在等待[並且什么都不做]。 對於[比較] 60 GB的文件,啟動時間會很明顯

如果你的文件是足夠大的真正的 ,你甚至會用完的分頁磁盤上的空間(即malloc返回NULL)。

對於mmap ,沒有這樣的問題。 映射文件時,可以立即開始使用它。 它將根據需要直接從該區域的后備存儲中“故障”[后者再次是文件系統中的文件]。 而且,如果你有[說] 1 TB文件, mmap處理就好了。

此外,您可以逐頁或任何頁面范圍(包括整個文件madvise(2)通過madvise(2)posix_madvise(2)控制映射策略。 madvise系統調用是相對輕量級的,因此使用它很好。 這是一個提示,但不會延遲應用程序的I / O. 如果I / O開始為提示進行預讀,那么內核將其作為后台活動完成。

你甚至可以告訴系統很快就需要一個給定的頁面[並且系統將其作為預取它的提示]或者你可以告訴系統不再需要該頁面[並且系統將釋放頁面緩沖存儲器]。

你可以對整個文件說“順序訪問”,這意味着系統會知道自動執行預讀,以及不再需要的頁面的釋放(即如果你當前正在訪問頁面N,然后系統在Nk之前釋放任何頁面)

當您執行read(2) ,無法告訴系統不再需要給定的內核FS頁面緩沖區。 它們會一直徘徊,直到物理RAM填滿[或超過給定的限制],這給整個內存系統增加了壓力。

實際上,使用read ,我已經看到在應用程序移動到文件的不同部分或完全不同的文件之后,用於FS緩沖區的內存量仍然很長。 事實上,我已經看到一個I / O密集型應用程序使用如此多的緩沖區,導致無關的[idle]進程將其頁面被盜並刷新到分頁磁盤。 當我停止I / O應用程序時,firefox需要花費幾分鍾來重新登錄並再次響應。

我為常規閱讀vs mmap做了一些廣泛的基准測試。 通過它們,mmap可以提高某些應用程序的速度。

請在此處查看我的答案: 以最有效的方式逐行閱讀*平台特定*

在我這樣做之前,我對mmap的好處持懷疑態度,但基准測試表明mmap是一個勝利者。

此外,如果您正在read(2) (針對速度)與fgets ,如果給定的行跨越讀取緩沖區邊界(即緩沖區的最后50個字符),則可能會因緩沖區移位而陷入困境擁有80個char行的前50個字節)。

請注意,在此鏈接頁面的評論中,還有另一個指向pastebin的鏈接到我的基准程序的更高版本,結果太大,無法在上述SO答案中發布基准並比較各種madvise選項

我很好奇這個,所以我試着對大小為1,2,4,8等的文件進行基准測試,一次使用mmap (M),一次使用read (R)(理論上一次調用fstat-ed)大小,但如果該調用返回了部分結果,它將重試)。 在讀取/ mmaping之后,以不可優化的方式訪問每個mmaped / read頁面的一個字節。

這是我的結果:

Size   M(µs)   R(µs)
1      9.5     4.2
2      10.8    4.5
4      8.4     3.8
8      8.6     3.8
16     7.3     4
32     7.8     3.5
64     8.3     3.9
128    9.2     4.6
256    8.6     4.7
512    10.6    5.1
1.0Ki  9.8     4.7
2.0Ki  10.1    5.4
4.0Ki  10.5    5.6
8.0Ki  10.4    6.9
16Ki   9.9     10
32Ki   14.4    12.8
64Ki   16.1    23.7
128Ki  28.1    41.1
256Ki  34.5    82.4
512Ki  57.9    154.6
1.0Mi  103.5   325.8
2.0Mi  188.5   919.8
4.0Mi  396.3   1963.2
8.0Mi  798.8   3885
16Mi   1611.4  7660.2
32Mi   3207.4  23040.2
64Mi   6712.1  84491.9

看起來read速度大約是16Ki 從那時起, mmap開始贏得大量時間( 64MiB文件獲得12倍)。

(在我的筆記本電腦上使用3.19在Linux上測試過,10 ^ 4次重復讀取到同一個文件。)

它沒有。 具體來說,當你調用它時,mmap()不會將整個文件加載到內存中,以某種方式加速訪問。 相反,它映射文件,也就是說,在內存中創建文件的索引(我使用松散的術語,承擔我),以便在您嘗試讀取/寫入該鍵時觸發頁面錯誤”。 所以凈效應是你有一個簡單的文件接口和一些延遲加載文件的內容。

我可以繼續,但其他人做得更好。 例如,見這里

暫無
暫無

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

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