1. 程式人生 > >Huge Page 是否是拯救效能的萬能良藥? • cenalulu's Tech Blog

Huge Page 是否是拯救效能的萬能良藥? • cenalulu's Tech Blog

本文將分析是否Huge Page在任何條件下(特別是NUMA架構下)都能帶來效能提升。

準備知識

在閱讀本文之前,需要讀者至少了解以下基礎知識

  • NUMA的基本概念,具體可參見部落格之前的科普介紹
  • 目前Linux基於多核CPU繁忙程度的執行緒排程機制,參看Chip Multi Processing aware Linux Kernel Scheduler論文

關於Huge Page

在正式開始本文分析前,我們先大概介紹下Huge Page的歷史背景和使用場景。

為什麼需要Huge Page 瞭解CPU Cache大致架構的話,一定聽過TLB Cache。Linux

系統中,對程式可見的,可使用的記憶體地址是Virtual Address。每個程式的記憶體地址都是從0開始的。而實際的資料訪問是要通過Physical Address進行的。因此,每次記憶體操作,CPU都需要從page table中把Virtual Address翻譯成對應的Physical Address,那麼對於大量記憶體密集型程式來說page table的查詢就會成為程式的瓶頸。所以現代CPU中就出現了TLB(Translation Lookaside Buffer) Cache用於快取少量熱點記憶體地址的mapping關係。然而由於製造成本和工藝的限制,響應時間需要控制在CPU Cycle級別的Cache容量只能儲存幾十個物件。那麼TLB Cache在應對大量熱點資料Virual Address
轉換的時候就顯得捉襟見肘了。我們來算下按照標準的Linux頁大小(page size) 4K,一個能快取64元素的TLB Cache只能涵蓋4K*64 = 256K的熱點資料的記憶體地址,顯然離理想非常遙遠的。於是Huge Page就產生了。 Tips: 這裡不要把Virutal Address和Windows上的虛擬記憶體搞混了。後者是為了應對實體記憶體不足,而將內容從記憶體換出到其他裝置的技術(類似於Linux的SWAP機制)。

什麼是Huge Page 既然改變不了TLB Cache的容量,那麼只能從系統層面增加一個TLB Cache entry所能對應的實體記憶體大小,從而增加TLB Cache所能涵蓋的熱點記憶體資料量。假設我們把Linux Page Size

增加到16M,那麼同樣一個容納64個元素的TLB Cache就能顧及64*16M = 1G的記憶體熱點資料,這樣的大小相較上文的256K就顯得非常適合實際應用了。像這種將Page Size加大的技術就是Huge Page

Huge Page是萬能的?

瞭解了Huge Page的由來和原理後,我們不難總結出能從Huge Page受益的程式必然是那些熱點資料分散且至少超過64個4K Page Size的程式。此外,如果程式的主要執行時間並不是消耗在TLB Cache Miss後的Page Table Lookup上,那麼TLB再怎麼大,Page Size再怎麼增加都是徒勞。在LWN的一篇入門介紹中就提到了這個原理,並且給出了比較詳細的估算方法。簡單的說就是:先通過oprofile抓取到TLB Miss導致的執行時間佔程式總執行時間的多少,來計算出Huge Page所能帶來的預期效能提升。 簡單的說,我們的程式如果熱點資料只有256K,並且集中在連續的記憶體page上,那麼一個64個entry的TLB Cache就足以應付了。說道這裡,大家可能有個疑問了:既然我們比較難預測自己的程式訪問邏輯是否能從開啟Huge Page中受益。反正Huge Page看上去只改了一個Page Size,不會有什麼效能損失。那麼我們就索性對所有程式都是用Huge Page好啦。 其實這樣的想法是完全錯誤的!也正是本文想要介紹的一個主要內容,在目前常見的NUMA體系下Huge Page也並非萬能鑰匙,使用不當甚至會使得程式或者資料庫效能下降10%。下面我們重點分析。

Huge Page on NUMA

Large Pages May Be Harmful on NUMA Systems一文的作者曾今做過一個實驗,測試Huge Page在NUMA環境的各種不同應用場景下帶來的效能差異。從下圖可以看到Huge Page對於相當一部分的應用場景並不能很好的提升效能,甚至會帶來高達10%的效能損耗。

效能下降的原因主要有以下兩點

CPU對同一個Page搶佔增多

對於寫操作密集型的應用,Huge Page會大大增加Cache寫衝突的發生概率。由於CPU獨立Cache部分的寫一致性用的是MESI協議,寫衝突就意味:

  • 通過CPU間的匯流排進行通訊,造成匯流排繁忙
  • 同時也降低了CPU執行效率。
  • CPU本地Cache頻繁失效

類比到資料庫就相當於,原來一把用來保護10行資料的鎖,現在用來鎖1000行資料了。必然這把鎖線上程之間的爭搶概率要大大增加。

連續資料需要跨CPU讀取(False Sharing)

從下圖我們可以看到,原本在4K小頁上可以連續分配,並因為較高命中率而在同一個CPU上實現locality的資料。到了Huge Page的情況下,就有一部分資料為了填充統一程式中上次記憶體分配留下的空間,而被迫分佈在了兩個頁上。而在所在Huge Page中佔比較小的那部分資料,由於在計算CPU親和力的時候權重小,自然就被附著到了其他CPU上。那麼就會造成:本該以熱點形式存在於CPU2 L1或者L2 Cache上的資料,不得不通過CPU inter-connect去remote CPU獲取資料。 假設我們連續申明兩個陣列,Array AArray B大小都是1536K。記憶體分配時由於第一個Page的2M沒有用滿,因此Array B就被拆成了兩份,分割在了兩個Page裡。而由於記憶體的親和配置,一個分配在Zone 0,而另一個在Zone 1。那麼當某個執行緒需要訪問Array B時就不得不通過代價較大的Inter-Connect去獲取另外一部分資料。

delays re-sulting from traversing a greater physical distance to reach a remote node, are not the most important source of performance overhead. On the other hand, congestion on interconnect links and in memory controllers, which results from high volume of data flowing across the system, can dramatically hurt performance.

Under interleaving, the memory latency re- duces by a factor of 2.48 for Streamcluster and 1.39 for PCA. This effect is entirely responsible for performance improvement under the better policy. The question is, what is responsible for memory latency improvements? It turns out that interleaving dramatically reduces memory controller and interconnect congestion by allevi- ating the load imbalance and mitigating traffic hotspots.

對策

理想

我們先談談理想情況。上文提到的論文其實他的主要目的就是討論一種適用於NUMA架構的Huge Page自動記憶體管理策略。這個管理策略簡單的說是基於Carrefour的一種對Huge Page優化的變種。(注:不熟悉什麼是Carrefour的讀者可以參看部落格之前的科普介紹或者閱讀原文) 下面是一些相關技術手段的簡要概括:

  • 為了減少只讀熱點資料跨NUMA Zone的訪問,可以將讀寫比非常高的Page,使用Replication的方式在每個NUMA Zone的Direct記憶體中都複製一個副本,降低響應時間。
  • 為了減少False Sharing,監控造成大量Cache Miss的Page,並進行拆分重組。將同一CPU親和的資料放在同一個Page中

現實

談完了理想,我們看看現實。現實往往是殘酷的,由於沒有硬體級別的PMU(Performance Monitor Unit)支援,獲取精準的Page訪問和Cache Miss資訊效能代價非常大。所以上面的理想僅僅停留在實驗和論文階段。那麼在理想實現之前,我們現在該怎麼辦呢? 答案只有一個就是測試

實際測試 實際測試的結果最具有說服力。所謂實際測試就是把優化物件給予真實環境的壓力模擬。通過對比開啟和關閉Huge Page時的效能差別來驗證Huge Page是否會帶來效能提升。當然大多數應用程式,要想模擬真實環境下的執行情況是非常困難的。那麼我們就可以用下面這種理論測試

理論測試 理論測試可以通過profile預估出Huge Page能夠帶來的潛在提升。具體原理就是計算當前應用程式執行時TLB Miss導致的Page Walk成本佔程式總執行時間的佔比。當然這種測試方式沒有把上文提到的那兩種效能損失考慮進去,所以只能用於計算Huge Page所能帶來的潛在效能提升的上限。如果計算出來這個值非常低,那麼可以認為使用Huge Page則會帶來額外的效能損失。具體方法見LWN上介紹的方法 具體的計算公式如下圖:

equation

如果沒有hardware的PMU支援的話,計算需要用到oprofilecalibrator

總結

並不是所有的優化方案都是0效能損失的。充分的測試和對於優化原理的理解是一個成功優化的前提條件。

Reference