cephfs內核客戶端性能追蹤

問題描述

測試cephfs內核客戶端的吞吐性能,direct寫時單個客戶端性能有上限,只能接近150 mb/s:

cephfs內核客戶端性能追蹤

查看網卡流量,並沒有打滿:

cephfs內核客戶端性能追蹤

查看集群負載也很低,osd磁盤很空閒,驗證多臺機器同時併發測試,總吞吐可以上去,懷疑單個客戶端的上限有瓶頸。

源碼分析

集群沒有打滿,網絡也不是瓶頸,那麼只能從內核客戶端cephfs的寫IO入手,尋找問題的根源。 cephfs內核客戶端寫IO的代碼在文件fs/ceph/file.c:

cephfs內核客戶端性能追蹤

從代碼實現看,主要流程是new_request, start_request, wait_request三個步驟。 直覺告訴我這裡的wait會被block住,跟蹤一下這裡的wait實現:

cephfs內核客戶端性能追蹤

先看超時的時間,傳入的是0,最終結果是LONG_MAX,差不多就是一直wait:

cephfs內核客戶端性能追蹤

接下來看條件的滿足:

cephfs內核客戶端性能追蹤

從kernel的註釋看,函數schedule_timeout就是sleep直到timeout:

cephfs內核客戶端性能追蹤

從源碼分析看,已經比較明確,一次請求下發後,只有等請求完成了才會進行下一次請求,IO並不是併發的下發給後端的集群。

接下來的問題是,每次請求的size如何決定? 這個和文件的layout屬性和當前寫的位置相關,如果從文件offset 0開始寫的話,以及採用默認屬性,最大就是ceph object size的大小,即4MB。 ceph的layout解釋可以參考官方文檔。

cephfs內核客戶端性能追蹤

實驗證明

調取文件屬性

為了更明顯的觀察延時,我們將文件的屬性調整一下,即從4m到64m:

cephfs內核客戶端性能追蹤

獲取文件inode

cephfs內核客戶端性能追蹤

文件對應的對象

cephfs內核客戶端性能追蹤

查看兩個對象對應的osd信息,分別對應osd 121和130:

cephfs內核客戶端性能追蹤

再次執行剛才的dd命令,並在兩個primary osd(121, 130)上觀察op的情況,並同時用ftrace,觀察kernel客戶端寫的過程。

osd機器OP請求

通過以下命令查看osd的op信息,ID為上面的121和130:

ceph daemon osd.ID dump_historic_ops

cephfs內核客戶端性能追蹤

上面是osd 121的信息,操作的對象是10000000388.00000000,op持續了426.153ms,主要耗費時間在網絡讀數據的延時和副本操作的延時。op開始時間16:04:19.049346,結束時間16:04:19.475499。

cephfs內核客戶端性能追蹤

這是osd 130的信息,操作的對象是10000000388.00000001,op持續了439.539ms。op開始時間16:04:19.491627,結束時間16:04:19.931166。

可以很清楚的看見,先寫第一個對象,再寫第二個對象,對象之間是沒有併發寫的,這區別於塊存儲,塊存儲的實現,至少librbd的實現,如果一次io對應多個object,多個請求是同時發出的,而不會等第一個對象完成了才下發第二個對象的IO,參見如下代碼:

cephfs內核客戶端性能追蹤

寫文件的客戶端ftrace信息

enable ftrace步驟:

cephfs內核客戶端性能追蹤

觀察日誌:

cephfs內核客戶端性能追蹤

這裡用了差不多500ms才開始下一個請求,而上面從osd端的分析看,第一個IO用了426ms才完成,osd完成IO後通知kernel客戶端有網絡延時,然後加上kernel調度的延時,差不多能夠匹配。

結論

通過源碼分析,然後分別從集群osd端和kernel客戶端進行驗證,direct的情況,cephfs性能確實有限制。但是,用戶也不用過於擔心性能跟不上,因為通常情況下,不會是direct寫,kernel客戶端有page cache,寫會非常快,

cephfs內核客戶端性能追蹤

更貼近真實的使用場景,用戶先寫數據,最後調用一次sync操作:

cephfs內核客戶端性能追蹤


分享到:


相關文章: