cgroup 限制虛擬機器頻寬後,虛擬機器裡top統計問題分析
阿新 • • 發佈:2019-02-20
今天遇到了一個問題。
用cgroup限制虛擬機器(qemu-kvm)的CPU佔比為宿主機的50%時。發現虛擬裡centos7系統,用top顯示一個死迴圈的程序,這個程序的佔比是50%。而我所認知時虛擬機器對限制應該不感知。應該顯示100%才對。
我又用qemu-kvm啟動了一個ubuntu的系統,發現ubuntu裡用top看一個死迴圈,這個程序顯示的是100%。
問題排查:
1 一開始我以為時top的工具統計的問題,我下載了top的原始碼。在兩個虛擬機器裡測試,發現新編譯的top和虛擬機器裡自帶的top結果相同。排除了top統計引起的問題。
2 這時候,核心版本可疑性就比較大了。我在ubuntu和centos用兩個系統中boot下面預設的config編譯。結果還是和原生的一樣。排除核心問題。
3 這個時候,懷疑核心配置選項問題了。我在ubuntu的系統裡用centos的config編譯核心。然後裝載重啟系統後,發現ubuntu的系統用top看之前的死迴圈的程序佔比變成了50%。
4 通過多次的ubuntu和centos原生的config對比和驗證後,發現核心的配置選項CONFIG_PARAVIRT_TIME_ACCOUNTING導致了centos和ubuntu在cgroup限制後,用top看虛擬機器的死迴圈程序的cpu使用率不同。Centos7使能了這個。
分析如下:
相關的核心的程式碼
static void update_rq_clock_task(struct rq *rq, s64 delta)
{
...此處省去xx行...
#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
if (static_key_false((¶virt_steal_rq_enabled))) {
steal = paravirt_steal_clock(cpu_of(rq));
steal -= rq->prev_steal_time_rq;
if (unlikely(steal > delta))
steal = delta;
rq->prev_steal_time_rq += steal;
delta -= steal;
}
#endif
rq->clock_task += delta;
...此處省去xx行...
}
程序的執行的物理時間是由rq->clock_task計算的,delta是程序在切換之前計算當前執行了多少時間。
當使能了CONFIG_PARAVIRT_TIME_ACCOUNTING後,delta會將cgroup限制的時間減去。導致在虛擬機器裡用top看while程序不是100%。
後來,在網上搜到了一篇文章解釋的很好。
http://oenhan.com/kvm-steal-time
用cgroup限制虛擬機器(qemu-kvm)的CPU佔比為宿主機的50%時。發現虛擬裡centos7系統,用top顯示一個死迴圈的程序,這個程序的佔比是50%。而我所認知時虛擬機器對限制應該不感知。應該顯示100%才對。
我又用qemu-kvm啟動了一個ubuntu的系統,發現ubuntu裡用top看一個死迴圈,這個程序顯示的是100%。
問題排查:
1 一開始我以為時top的工具統計的問題,我下載了top的原始碼。在兩個虛擬機器裡測試,發現新編譯的top和虛擬機器裡自帶的top結果相同。排除了top統計引起的問題。
2 這時候,核心版本可疑性就比較大了。我在ubuntu和centos用兩個系統中boot下面預設的config編譯。結果還是和原生的一樣。排除核心問題。
3 這個時候,懷疑核心配置選項問題了。我在ubuntu的系統裡用centos的config編譯核心。然後裝載重啟系統後,發現ubuntu的系統用top看之前的死迴圈的程序佔比變成了50%。
4 通過多次的ubuntu和centos原生的config對比和驗證後,發現核心的配置選項CONFIG_PARAVIRT_TIME_ACCOUNTING導致了centos和ubuntu在cgroup限制後,用top看虛擬機器的死迴圈程序的cpu使用率不同。Centos7使能了這個。
分析如下:
相關的核心的程式碼
static void update_rq_clock_task(struct rq *rq, s64 delta)
{
...此處省去xx行...
#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
if (static_key_false((¶virt_steal_rq_enabled))) {
steal = paravirt_steal_clock(cpu_of(rq));
steal -= rq->prev_steal_time_rq;
if (unlikely(steal > delta))
steal = delta;
rq->prev_steal_time_rq += steal;
delta -= steal;
}
#endif
rq->clock_task += delta;
...此處省去xx行...
}
程序的執行的物理時間是由rq->clock_task計算的,delta是程序在切換之前計算當前執行了多少時間。
當使能了CONFIG_PARAVIRT_TIME_ACCOUNTING後,delta會將cgroup限制的時間減去。導致在虛擬機器裡用top看while程序不是100%。
後來,在網上搜到了一篇文章解釋的很好。
http://oenhan.com/kvm-steal-time