您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關使用THP的配置建議及關閉方法是什么,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
我們之前在生產環境上遇到過很多起由操作系統的某些特征引起的性能抖動案例,其中 THP 作案次數較多,因此下面將和大家分享 THP 引起性能抖動的原因、典型的現象,分析方法等,在最后給出使用THP 時的配置建議及關閉方法。
世界并不是非黑即白的,THP 也是內核的一個重要特征,且持續在演進,其目的是通過將頁表項映射更大的內存,來減少 Page Fault,從而提升 TLB (Translation Lookaside Buffer,由存儲器管理單元用于改進虛擬地址到物理地址的轉譯速度)的命中率。結合存儲器層次結構設計原理可知,當程序的訪存局部性較好時,THP 將帶來性能提升,反之 THP 的優勢不僅喪失,還有可能化身為惡魔,引起系統的不穩定。遺憾的是數據庫的負載訪問特征通常是離散的。
在陳述 THP 引起的負面現象前,先來和大家一起回憶下,Linux 操作系統是如何管理物理內存的。對于不同的體系結構,內核對應不同的內存布局圖。其中用戶空間通過多級頁表進行映射來節約映射管理所需的空間,而內核空間為了簡單高效采用線性映射。在內核啟動時,物理頁面將加入到伙伴系統 (Buddy System)中,用戶申請內存時分配,釋放時回收。為了照顧慢速設備及兼顧多種 workload,Linux 將頁面類型分為匿名頁(Anon Page)和文件頁 (Page Cache),及 swapness,使用 Page Cache 緩存文件 (慢速設備),通過 swap cache 和 swapness 交由用戶根據負載特征決定內存不足時回收二者的比例。為了盡可能快的響應用戶的內存申請需求并保證系統在內存資源緊張時運行,Linux 定義了三條水位線 (high,low,min),當剩余物理內存低于 low 高于 min 水位線時,在用戶申請內存時通過 kswapd 內核線程異步回收內存,直到水位線恢復到 high 以上,若異步回收的速度跟不上線程內存申請的速度時,將觸發同步的直接內存回收,也就是所有申請內存的線程都同步的參與內存回收,一起將水位線抬上去后再獲得內存。這時,若需要回收的頁面是干凈的,則同步引起的阻塞時間就比較短,反之則很大(比如幾十、幾百ms 甚至 s 級,取決于后端設備速度)。除水位線外,當申請大的連續內存時,若剩余物理內存充足,但碎片化比較嚴重時,內核在做內存規整的時候,也有可能觸發直接內存回收(取決于碎片化指數,后面會介紹)。因此內存直接回收和內存規整是進程申請內存路徑上的可能遇到的主要延遲。而在訪存局部性差的負載下,THP 將成為觸發這兩個事件的幕后黑手。
我們在多個用戶現場發現當分配 THP 引發性能波動時,其最典型的特征就是 Sys CPU 使用率飆升,這種特征的分析比較簡單,通過 perf 抓取 on-cpu火焰圖,我們就可以看到我們服務所有處于 R 狀態的線程都在做內存規整,且缺頁異常處理函數為 do_huge_pmd_anonymous_page,說明當前系統沒有連續 2M 的物理內存,因此觸發了直接內存規整,直接內存規整的邏輯是很耗時的,是導致 sys 利用率升高的原因。
真實的系統往往是復雜的,當分配 THP 或分配其它高階內存時,系統并不會做直接內存規整,留下上述那么典型的犯罪特征,而是混合其他行為,比如直接內存回收。直接內存回收的參與讓事情變的稍微有些復雜和令人疑惑,比如我們最初從客戶現場看到 normal zone 的剩余物理內存高于 high 水位線,可系統為啥不停的在做直接內存回收呢?我們深入到慢速內存分配的處理邏輯中可知,慢速內存分配路徑主要有幾個步驟:1. 異步內存規整;2. 直接內存回收;3. 直接內存規整;4. oom 回收,每個步驟處理完成后,都會嘗試分配內存,如果可分配了,則直接返回頁面,略過后面的部分。其中內核為伙伴系統的每個 order 提供了碎片指數來表示內存分配失敗是由于內存不足還是碎片化引起的。和其關聯的是 /proc/sys/vm/extfrag_threshold, 當接近 1000 時,表示分配失敗主要和碎片化相關,此時內核會傾向于做內存規整,當接近 0 時,表示分配失敗和內存不足關聯更大,則內核會傾向于做內存回收。因此產生了在高于 high 水位線的時候,頻繁進行直接內存回收的現象 。而由于 THP 的開啟和使用占據了高階內存,因此加速了內存碎片化引起的性能抖動問題。
對此特征,判定方法如下:
運行 sar -B 觀察 pgscand/s ,其含義為每秒發生的直接內存回收次數,當在一段時間內持續大于0時,則應繼續執行后續步驟進行排查;
運行 cat /sys/lernel/debug/extfrag/extfrag_index
觀察內存碎片指數,重點關注 order >= 3 的碎片指數,當接近 1.000 時,表示碎片化嚴重,當接近 0 時表示內存不足;
運行 cat /proc/buddyinfo, cat /proc/pagetypeinfo
查看內存碎片情況, 指標含義參考 (https://man7.org/linux/man-pages/man5/proc.5.html),同樣關注 order >= 3 的剩余頁面數量,pagetypeinfo 相比 buddyinfo 展示的信息更詳細一些,根據遷移類型 (伙伴系統通過遷移類型實現反碎片化)進行分組,需要注意的是,當遷移類型為 Unmovable 的頁面都聚集在 order < 3 時,說明內核 slab 碎片化嚴重,我們需要結合其他工具來排查具體原因,在本文就不做過多介紹了;
對于 CentOS 7.6 等支持 BPF 的 kernel 也可以運行我們研發的 drsnoop,compactsnoop 工具對延遲進行定量分析,使用方法和解讀方式請參考對應文檔;
(Opt) 使用 ftrace 抓取 mm_page_alloc_extfrag 事件,觀察因內存碎片從備用遷移類型“盜取”頁面的信息;
我們在 AARCH64 服務器上,遇到過服務剛啟動就占用幾十個 G 物理內存的場景,通過觀察 /proc/pid/smaps 文件可以看到內存大部分用于 THP, 且 AARCH64 的 CentOS 7內核編譯時選用的 PAGE SIZE 為 64K,因此相比 X86_64 平臺的內存用量差出很多倍。在定位的過程中我們也順便修復了 jemalloc 未完全關閉 THP 的bug: fix opt.thp:never still use THP with base_map。
對于未對訪存局部性進行優化的程序或負載本身就是離散的訪存程序而言,將 THP 以及 THP defrag 設置為始終開啟,對長時間運行的服務而言有害無益,且內核從 4.6 版本內核版本起才對 THP 的 defrag 提供了 defer,defer + madvise 等優化。因此對于我們常用的 CentOS 7 3.10 版本的內核來說,若程序需要使用 THP,則建議將 THP 的開關設置為 madvise,在程序中通過 madvise 系統調用來分配 THP, 否則設置成 never 禁用掉是最佳選擇:
查看當前的 THP 模式:
cat /sys/kernel/mm/transparent_hugepage/enabled
若值是 always 時,執行:
echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag
完成關閉操作。 需要注意的是為防止服務器重啟失效,應將這兩個命令寫入到 .sevice 文件中,交給 systemd 進行管理。
上述就是小編為大家分享的使用THP的配置建議及關閉方法是什么了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。