生成大量臟頁會阻塞同步寫入
我們有程序在後台寫入大文件。我們希望這些對其他流程的影響最小。
這是在 SLES11 SP4 上實現的測試。伺服器擁有大量記憶體,可以創建 4GB 的髒頁。
> dd if=/dev/zero of=todel bs=1048576 count=4096 4096+0 records in 4096+0 records out 4294967296 bytes (4.3 GB) copied, 3.72657 s, 1.2 GB/s > dd if=/dev/zero of=zer oflag=sync bs=512 count=1 1+0 records in 1+0 records out 512 bytes (512 B) copied, 16.6997 s, 0.0 kB/s real 0m16.701s user 0m0.000s sys 0m0.000s > grep Dirty /proc/meminfo Dirty: 4199704 kB
這是我到目前為止的調查:
- SLES11 SP4 (3.0.101-63)
- 類型 ext3 (rw,nosuid,nodev,noatime)
- 截止日期調度程序
- 當時超過 120GB 的可回收記憶體
- dirty_ratio 設置為 40%,dirty_background_ratio 10%,30s 過期,5s writeback
以下是我的問題:
- 在測試結束時有 4GB 臟記憶體,我得出結論,在上述測試中沒有呼叫 IO 調度程序。是對的嗎?
- 由於第一個 dd 完成後緩慢仍然存在,我得出結論,這個問題也與核心分配記憶體或 dd 填充他的緩衝區時發生的任何“寫入時複製”無關(dd 總是從同一個 buf 寫入)。
- 有沒有辦法更深入地調查被阻止的內容?有什麼有趣的櫃檯值得關注嗎?對爭論的來源有任何想法嗎?
- 我們正在考慮減少dirty_ratio值,或者在同步模式下執行第一個dd。還有什麼其他的調查方向嗎?將第一個 dd 同步放置有缺點嗎?恐怕它會優先於其他執行非同步寫入的“合法”程序。
也可以看看
https://www.novell.com/support/kb/doc.php?id=7010287
http://yarchive.net/comp/linux/dirty_limits.html
編輯:
同一設備下有一個**ext2文件系統。**在這個設備上,根本沒有凍結!唯一的性能影響發生在刷新臟頁期間,同步呼叫可能需要 0.3 秒,這與我們使用 ext3 文件系統的體驗相差甚遠。
編輯2:
在@Matthew Ife 評論之後,我嘗試在沒有 O_TRUNC 的情況下進行同步寫入打開文件,你不會相信結果!
> dd if=/dev/zero of=zer oflag=sync bs=512 count=1 > dd if=/dev/zero of=todel bs=1048576 count=4096 > dd if=/dev/zero of=zer oflag=sync bs=512 count=1 conv=notrunc 1+0 records in 1+0 records out 512 bytes (512 B) copied, 0.000185427 s, 2.8 MB/s
dd 正在使用參數打開文件:
open("zer", O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, 0666) = 3
使用 notrunc 選項進行更改,現在是
open("zer", O_WRONLY|O_CREAT|O_SYNC, 0666) = 3
同步寫入立即完成!
好吧,這對我的案例來說並不完全令人滿意(我正在以這種方式進行 msync 。但是我現在能夠跟踪 write 和 msync 的不同之處!
最後編輯:我不敢相信我打了這個: https ://www.novell.com/support/kb/doc.php?id=7016100
實際上在 SLES11 下 dd 是用
open("zer", O_WRONLY|O_CREAT|O_DSYNC, 0666) = 3
和 O_DSYNC == O_SYNC!
結論:
對於我的案例,我可能應該使用
dd if=/dev/zero of=zer oflag=dsync bs=512 count=1 conv=notrunc
在 SLES11 下,無論 strace 說什麼,執行 oflag=sync 都會真正執行 oflag=dsync。
有幾件事我很想知道結果。
- 最初創建大文件,
fallocate
然後寫入它。- 將dirty_background_bytes 設置得低得多(比如1GiB)並使用CFQ 作為調度程序。請注意,在此測試中,在大執行中間執行小執行可能是更好的表示。
因此,對於選項 1,您可能會發現您避免了所有
data=ordered
語義,因為塊分配已經(並且很快)完成,因為它是通過預先分配的,fallocate
並且元數據是在寫入之前設置的。測試是否真的是這樣是很有用的。我有一些信心,雖然它會提高性能。對於選項 2,您可以多使用 ionice。Deadline 明顯比 CFQ 快,儘管 CFQ 嘗試組織每個程序的 IO,以便您發現它可以讓您在每個程序中更好地共享 IO。
我在某處讀到(現在找不到來源),dirty_background_ratio 將阻止針對單個送出程序的寫入(有效地使大程序變慢),以防止一個程序餓死所有其他程序。鑑於我現在能找到的關於這種行為的資訊很少,我不太相信這會奏效。
哦:我應該指出這
fallocate
依賴於範圍,你需要使用 ext4。