2017-09-13 101 views
2

以另一種方式提出問題,您是否可以確認當您mmap()實際訪問已存在於頁面緩存中的確切物理頁面的文件時?mmap是否直接訪問頁面緩存或頁面緩存的副本?

我問,因爲我正在測試一臺內存爲1TB的192核心機器上,在測試之前預先緩存到頁面緩存中的400GB數據文件上(只需刪除緩存,然後執行md5sum在文件上)。假設它們都(基本上)返回相同的內存區域(或者可能是相同的內存區域,但以某種方式映射多次),我最初分別有192個線程分別映射文件。因此,我假設兩個使用兩個不同映射到同一文件的線程都可以直接訪問相同的頁面。 (讓我們忽略NUMA在這個例子中,雖然他們顯然是在更高的線程數量顯著。)

然而,在實踐中,我發現性能會得到可怕在更高線數時,每個線程分別mmapped文件。當我們刪除它,而只是做了一個傳入線程的mmap(所有線程都直接訪問同一個內存區域),那麼性能會大大提高

這一切都很棒,但我試圖找出原因。如果實際上映射文件只是授予對現有頁面緩存的直接訪問權限,那麼我認爲它應該映射多少次無關緊要 - 它應該全部放在同一個地方。

但是考慮到有這樣的性能成本,在我看來,實際上每個mmap都是獨立冗餘的(可能是通過從頁面緩存複製,或者可能通過從磁盤再次讀取)。

你可以評論爲什麼我看到共享訪問同一內存之間的這種不同的性能,而不是映射相同的文件?

謝謝,我感謝您的幫助!

+0

這是一個很好的問題。我不認爲我能夠回答,但提供一些建議。 1 /爲什麼不介紹它? perf應該能夠很容易地告訴你瓶頸的位置(我希望)。我的猜測是,你打到mmap(小)的開銷,但在192線程,它不會擴展。另外,你有沒有嘗試使用巨大的頁面? – Aissen

+0

因爲所有有趣的東西都發生在內核的深處,所以配置文件很棘手。就我的應用程序所知,它只是訪問內存 - 但是在內存映射,虛擬內存,頁面緩存,L3緩存和NUMA節點之間,還有很多移動部件需要注意。這就是說,我同意有更多的工作要做,以解決這個問題,但我希望有一個比我更熟悉內核知識的人可以給出一些建議,至少在*理論中應該發生什麼,就像在實踐中指導我的測試。 – quinthar

+0

是的,但通常perf會知道內核在哪裏花費時間,如果你有正確的符號附加。關於你的問題,我不知道問題的根源是什麼。您是否嘗試在較小的機器上重現它? – Aissen

回答

1

我想我找到了我的答案,它處理頁面目錄。答案是肯定的,同一文件的兩個mmapped區域將訪問相同的基礎頁面緩存數據。但是,每個映射需要將每個虛擬頁面獨立映射到物理頁面 - 這意味着頁面目錄中的條目數量是訪問相同RAM的數量的兩倍。

基本上,每個mmap()都會在虛擬內存中創建一個新的範圍。該範圍的每一頁對應於一頁物理內存,並且該映射存儲在分層頁面目錄中 - 每4KB頁面有一個條目。因此,大型區域的每個mmap()都會在頁面目錄中生成大量條目。

我的猜測是實際上並沒有將它們全部預先定義,這就是爲什麼mmap()即使對於巨型文件也是即時調用的原因。但隨着時間的推移,它可能必須建立這些條目,因爲mmapped範圍內存在錯誤,這意味着隨着時間的推移它會被填寫。這種額外的工作來填充頁面目錄可能是爲什麼使用不同mmap的線程比共享相同mmap的線程慢。我打賭內核需要在取消映射範圍時清除所有這些條目 - 這就是爲什麼unmmap()速度很慢。

(還有轉換後備緩衝器,但這是每個CPU,和這麼小,我不認爲事情在這裏多。)

無論如何,這聽起來就像重新映射相同的區域只是增加了額外的開銷,因爲我覺得沒有收穫。