寫回記憶體(dirty
)似乎被限制在甚至小於dirty_background_ratio。它受到什麼限制?這個限制是如何計算的?
我一直在測試 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
田野atop
。dd
命令執行時,該值dirty
穩定在 0.5G 左右。這明顯小於臟背景門檻值(0.77G)!怎麼會這樣?我錯過了什麼?
dirty_expire_centisecs
是3000,所以我認為這不是原因。我什至嘗試降低dirty_expire_centisecs
到 100 和dirty_writeback_centisecs
10,看看這是否有限制dirty
。這並沒有改變結果。作為調查的一部分,我最初寫了這些觀察結果:為什麼在 2013 年報告了“USB 記憶棒失速”問題?為什麼現有的“No-I/O 臟節流”程式碼沒有解決這個問題?
我了解兩個門檻值之間的中間值 - 15% = 1.155G - write() 呼叫開始在曲線上受到限制(延遲)。但是在這個天花板之下時不會增加延遲;允許生成臟頁的程序“自由執行”。
據我了解,節流旨在將臟記憶體保持在 15% 或以上,並防止達到 20% 的硬限制。它並不為所有情況提供保證。但我正在用一個
dd
命令測試一個簡單的案例;我認為它應該簡單地限制 write() 呼叫以匹配設備實現的寫出速度。(沒有簡單的保證,因為有一些複雜的異常。例如,節流程式碼將其施加的延遲限制為最大 200 毫秒。但如果程序的目標速率限制小於每秒一頁,則不會;在在這種情況下,它將應用嚴格的速率限制。)
- 文件/sysctl/vm.txt – Linux v4.18
- 無 I/O 臟節流——2011 LWN.net。
- >
(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) / 2
中global_dirtyable_memory()
的