Linux

寫回記憶體(dirty)似乎被限制在甚至小於dirty_background_ratio。它受到什麼限制?這個限制是如何計算的?

  • February 21, 2019

我一直在測試 Linux 4.18.16-200.fc28.x86_64。根據free -h.

我有vm.dirty*sysctl 的預設值。 dirty_background_ratio是 10,dirty_ratio是 20。根據我讀過的所有內容,我希望 Linux 在達到 10% 的 RAM 時開始寫出臟記憶體:0.77G。當臟記憶體達到 RAM 的 20%:1.54G 時,緩衝的 write() 呼叫應該阻塞。

我跑著dd if=/dev/zero of=~/test bs=1M count=2000看著dirty田野atopdd命令執行時,該值dirty穩定在 0.5G 左右。這明顯小於臟背景門檻值(0.77G)!怎麼會這樣?我錯過了什麼?

dirty_expire_centisecs是3000,所以我認為這不是原因。我什至嘗試降低dirty_expire_centisecs到 100 和dirty_writeback_centisecs10,看看這是否有限制dirty。這並沒有改變結果。

作為調查的一部分,我最初寫了這些觀察結果:為什麼在 2013 年報告了“USB 記憶棒失速”問題?為什麼現有的“No-I/O 臟節流”程式碼沒有解決這個問題?


我了解兩個門檻值之間的中間值 - 15% = 1.155G - write() 呼叫開始在曲線上受到限制(延遲)。但是在這個天花板之下時不會增加延遲;允許生成臟頁的程序“自由執行”。

據我了解,節流旨在將臟記憶體保持在 15% 或以上,並防止達到 20% 的硬限制。它並不為所有情況提供保證。但我正在用一個dd命令測試一個簡單的案例;我認為它應該簡單地限制 write() 呼叫以匹配設備實現的寫出速度。

(沒有簡單的保證,因為有一些複雜的異常。例如,節流程式碼將其施加的延遲限制為最大 200 毫秒。但如果程序的目標速率限制小於每秒一頁,則不會;在在這種情況下,它將應用嚴格的速率限制。)

(dirty_background_ratio +dirty_ratio)/2 總共臟數據…是我們開始限制程序時的髒數據量——Jan Kara,2013

  • >

使用者會注意到,一旦超過全域(背景 + 臟)/2=15% 門檻值,應用程序將受到限制,然後在 17.5% 左右平衡。在更新檔之前,行為是將其限制在 20% 的可臟記憶體

– 送出 143dfe8611a6,“寫回:IO-less balance_dirty_pages()

  • >

預設情況下,記憶體管理子系統將嘗試將臟頁限制為系統記憶體的最大 15%。有一個名為 balance_dirty_pages() 的“神奇函式”,如果需要,它會限制程序污染大量頁面,以匹配頁面被污染的速率和它們可以被清除的速率。”——回寫和控制組,2015 LWN.net。

查看Documentation/sysctl/vm.txt

臟比

包含,作為**包含空閒頁面和可回收頁面的總可用記憶體的百分比,**正在生成磁碟寫入的程序本身將開始寫出臟數據的頁面數。

總可用記憶體不等於總系統記憶體

可用記憶體在global_dirtyable_memory()中計算。它等於可用記憶體量加上頁面記憶體。它不包括可交換頁面(即匿名記憶體分配,不支持文件的記憶體)。

此行為自Linux 3.14 (2014)起適用。在此更改之前,可交換頁麵包含在 global_dirtyable_memory() 總數中。

執行dd命令時的範例統計資訊:

$ while true; do grep -E '^(Dirty:|Writeback:|MemFree:|Cached:)' /proc/meminfo | tr '\n' ' '; echo; sleep 1; done
MemFree:         1793676 kB Cached:          1280812 kB Dirty:                 4 kB Writeback:             0 kB
MemFree:         1240728 kB Cached:          1826644 kB Dirty:            386128 kB Writeback:         67608 kB
MemFree:         1079700 kB Cached:          1983696 kB Dirty:            319812 kB Writeback:        143536 kB
MemFree:          937772 kB Cached:          2121424 kB Dirty:            312048 kB Writeback:        112520 kB
MemFree:          755776 kB Cached:          2298276 kB Dirty:            389828 kB Writeback:         68408 kB
...
MemFree:          136376 kB Cached:          2984308 kB Dirty:            485332 kB Writeback:         51300 kB
MemFree:          101340 kB Cached:          3028996 kB Dirty:            450176 kB Writeback:        119348 kB
MemFree:          122304 kB Cached:          3021836 kB Dirty:            552620 kB Writeback:          8484 kB
MemFree:          101016 kB Cached:          3053628 kB Dirty:            501128 kB Writeback:         61028 kB

最後一行顯示大約 3,150,000 kB 的“可用”記憶體,總共有 562,000 kB 數據正在回寫或等待回寫。這使它成為17.8%。儘管該比例似乎在該水平上下波動,並且更經常接近 15%。 編輯:雖然這些數字看起來更近,但請不要相信這種方法。它仍然不是正確的計算,它可能會給出非常錯誤的結果。請參閱此處的後續內容。


我發現這很難:

我注意到balance_dirty_pages() 中有一個跟踪點,可用於“分析節流算法的動態”。所以我用perf

$ sudo perf list '*balance_dirty_pages'

List of pre-defined events (to be used in -e):

 writeback:balance_dirty_pages                      [Tracepoint event]
...
$ sudo perf record -e writeback:balance_dirty_pages dd if=/dev/zero of=~/test bs=1M count=2000
$ sudo perf script

它表明dirty(以 4096 字節頁面測量)低於我的預期,因為setpoint很低。我追踪了程式碼;這意味著freerun跟踪點定義(thresh + bg_thresh) / 2global_dirtyable_memory()

引用自:https://unix.stackexchange.com/questions/480467