天天看點

如何衡量系統記憶體健康程度: memdelay簡介簡介主要功能為什麼需要它原理介紹主要設計結構接口設計

簡介

最近在upstream上, Johannes Weiner發了一個memdelay的patch, 主要是衡量系統記憶體的健康程度, 在對它進行分析和優化之後, 做了一個簡單的總結

memdelay是衡量一個系統(memcg)中記憶體的健康程度的一個監控系統, 可以用來評價一個memcg的limit是否設定得合理

主要功能

  • 監控每個task因為記憶體短缺導緻的延遲
  • 監控每個memcg因為記憶體短缺導緻的延遲
  • 監控每個memcg因為記憶體短缺産生了多大的性能影響

為什麼需要它

在一個系統中, 能跑多少應用, 跑少了, 浪費記憶體, 跑多了, 性能下降, 多少是個合理的值, 是個比較難捉摸的事情, memdelay就是為此來做一個簡單的評估

一個很簡單的模型, 應用一共需要1g的記憶體, 如果提供了1g的記憶體給他, 那麼就什麼問題都沒有了, 但是實際情況中, 很多記憶體都是read_once, 是以為了提高使用率, 給他900m也是能跑的, 隻不過這些記憶體都分時複用了, 一般情況下, 給個800m, 也能跑, 700m也能跑, 分時複用得越厲害, 性能就會越差. 那麼臨界點是多少, 讓memdelay來告訴你

原理介紹

memdelay的思想很簡單, 就是在一個memcg中, 因為記憶體短缺引起的延遲除以任務實際運作時間的百分比. 如果系統記憶體很富裕的話, 這個時間基本上為0. 在記憶體很緊張的情況中, 這個百分比可以達到50%, 可以說系統一半時間在幹活, 一半時間在做記憶體這件事情上白忙.

主要設計結構

這個簡單介紹一下設計概要, 把cpu的運作狀态分3個種類

  • MDS_NONE, 表示沒有任何記憶體造成的延遲
  • MDS_SOME, 表示既有記憶體延遲, 又有其他延遲, 比如IO
  • MDS_FULL, 隻有記憶體延遲

接口設計

memdelay的接口是memcg目錄下的檔案memory.memdelay,

cat memory.memdelay
18359583 17087353 1272230 (總的記憶體延遲 前台延遲 背景延遲)
0.46 0.11 0.03 (MDS_SOME狀态1分鐘, 5分鐘, 15分鐘, 百分比)
3.97 2.09 0.85 (MDS_FULL狀态1分鐘, 5分鐘, 15分鐘, 百分比)           

百分比越高, 說明越多的時間花在了記憶體複用上, 對性能的影響比較大

那如何把cpu區分出這3種狀态, 那就是根據這個cpu上不同性質的task的數量來定

把每個task根據記憶體的狀況, 分别記成sleep, iowait, runnable, delayed, delayed_active, 分别表示的含義是

  • sleep, task睡眠, 不在runqueue上
  • iowait, 在等io
  • runnable, 處于runqueue上
  • delayed, 因為記憶體短缺, 目前沒在運作, 比如進入direct reclaim之後, 被排程出去了
  • delayed_active, 因為記憶體短缺, 正在運作, 比如正在做direct reclaim

那麼如何判斷一個task是處于sleep, iowait, runnable, delayed, delayed_active中的哪種狀态呢, 這就需要在系統中, 記錄任務狀态的變化過程, 從代碼的實作角度簡單得來說, 就是在排程對task進行處理的時候插樁

如何衡量系統記憶體健康程度: memdelay簡介簡介主要功能為什麼需要它原理介紹主要設計結構接口設計

根據上面所訴的根據記憶體的使用情況來對task的狀态分類, 進而來确定cpu的狀态, 判斷規則如下

  • 有delayed_active的任務下, 有iowait為MDS_SOME, 否則就是MDS_FULL
  • 有delayed的任務下, 有runable或者iowait為MDS_SOME, 否則就是MDS_FULL
  • 其他情況就是MDS_NONE

memcg記憶體延遲統計

每個memcg建立一個per cpu的資料結構memdelay_domain_cpu, 記錄cpu的這3種狀态, 每5s統計一次, 就可以計算出一個memcg裡面所有cpu, MDS_NONE占多少百分比, MDS_SOME占多少百分比, MDS_FULL占多少百分比, 就可以看出記憶體影響了多少的性能

測試檢驗

以下是從測試的角度來檢驗以下memdelay的功能

/sdk目錄下有17G的檔案, 用來準備做buffer io
time sh -c 'vmtouch -e  /sdk/*; vmtouch -t /sdk/*'           

在沒有memcg的限制的情況下, time結果, (memdelay的結果肯定全是0, 因為沒有前台延遲)

real    0m32.044s
user    0m1.192s
sys     0m9.052s           

在把memcg限制到1G的情況下, time結果

real    0m36.561s
user    0m0.961s
sys     0m16.177s           

memdelay的結果

4191438 4191438 0
0.00 0.00 0.00
4.52 1.04 0.34           

從上面的結果可以看出, memcg限制為1g的時候, 前台回收總共延遲了4s, 剛好是上面的32s到36s的差距, 4s/36s等于1/9, 也就是0.11, 在百分比的那一欄, 第一列是1分鐘的滑動平均, 因為隻跑了30s, 是以隻有一半, 4.52%也很好得展現了記憶體前台延遲對應用拖慢了多少性能