本文介紹Alibaba Cloud Linux 2系統的ECS實例中ext4文件系統的Buffer I/O寫性能不符合預期問題的原因及解決方案。
問題描述
在ext4文件系統中執行常規的緩存異步I/O(Buffer I/O)寫操作時,可能會觀察到性能表現不符合預期的情形。存在該問題的ECS實例有以下特征:
鏡像:
aliyun-2.1903-x64-20G-alibase-20190327.vhd
及之后所有的鏡像版本。內核:
kernel-4.19.24-9.al7
及之后所有的內核版本。通過
dioread_nolock
和nodelalloc
兩個選項掛載ext4文件系統。說明關于如何查看文件系統類型及掛載選項,請參見查看文件系統類型及掛載選項。
驗證性能表現不符合預期的典型場景如下:
關于ECS塊存儲的性能,請參見塊存儲性能。
場景一:使用
cp
命令拷貝大文件到ext4文件系統中,耗時很久,每秒拷貝速度只能達到30MB/s左右。場景二:使用類似如下不帶同步標志(Sync Flag)的
dd
命令寫文件到ext4文件系統中,耗時很久。dd if=/dev/zero of=/mnt/badfile bs=10M count=1000
且在終端中通過
iostat -xm 1
命令觀察對應磁盤的寫入速度時,wMB/s列的值只有30MB/s左右。系統顯示類似如下。avg-cpu: %user %nice %system %iowait %steal %idle 0.00 0.00 12.77 0.00 0.00 87.23 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util vda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 vdb 0.00 7194.00 0.00 57.00 0.00 28.05 1008.00 0.02 17.81 0.00 17.81 0.39 2.20
問題原因
從文件系統代碼層面分析,該問題的根本原因是當文件系統以dioread_nolock
和nodelalloc
組合選項掛載時,產生了大量內核中被稱為“unwritten extents”、大小為4KB的臟頁(Dirty Page);由于ext4文件系統處理邏輯的缺陷,這些4KB的臟頁在寫回的時候并不會被合并成若干個大頁進行寫回,而是直接以小頁的形式被處理。從Perf工具觀察內核寫回頁面緩存的過程,發現處理過程主要發生在ext4文件系統的ext4_writepages()
函數內部,在查找和映射4KB臟頁的邏輯中耗費了大量的時間,從而造成文件寫入性能極低。
解決方案
該問題為已知問題,暫無固化解決方案。您可以參考以下步驟臨時解決此問題:
參考以下命令,重新掛載ext4文件系統,取消同時使用
dioread_nolock
和nodelalloc
的掛載選項組合。sudo mount -o remount,delalloc <$Device> <$Mount_point>
說明<$Device>:指掛載ext4文件系統的設備名。
<$Mount_point>:指ext4文件系統的掛載點。
修改
/etc/fstab
文件,刪除ext4文件系統的nodelalloc
選項(默認為delalloc
),以確保系統開機自動掛載。
查看文件系統類型及掛載選項
查看目錄所在磁盤的文件系統類型及掛載選項,參考步驟如下:
登錄ECS實例,參考以下命令,確認目錄所在的磁盤分區。
df <$DIR> | grep -v Filesystem | awk '{ print $1 }'
說明<$DIR>指寫操作的目標目錄。
參考以下命令,查看目標磁盤分區的文件系統類型以及掛載選項。
mount | grep -w <$Partition> | grep ext4 | grep -w dioread_nolock | grep -w nodelalloc
說明<$Partition>指上一步獲取的磁盤分區名。