1. ホーム
  2. linux

LinuxでCPU使用率の正確な計算をパーセンテージで教えてください。

2023-09-22 02:11:31

質問

これは何度も聞かれた質問ですが、私が見つけた中では、よくサポートされた回答はありませんでした。

多くの人が top コマンドの使用を勧めていますが、top を一度実行すれば (例えば 1 秒ごとに Cpu の使用率を収集するスクリプトがあるため)、常に同じ Cpu 使用率の結果が返されます ( 例 1 , 例2 ).

CPU 使用率をより正確に計算する方法として、以下のように /proc/stat の最初の 4 つのフィールドのみを使用します。 /proc/stat の最初の 4 つのフィールドのみを使用して計算します (一例として ここで ).

/proc/stat/ は、Linux カーネル 2.6.33 の時点で、CPU コアあたり 10 フィールドを持ちます!

また、こんなのもありました。 Linux で /proc/stat を使用して CPU 使用率を正確に計算する の質問は同じ問題を指摘しています - 他のほとんどの質問は多くのフィールドのうち4つしか考慮に入れていません - しかし、ここで与えられた答えは "私は思う" (not certain) で始まり、それを除いて、それは最初の7フィールドにのみ関係しています (10フィールド中 /proc/stat/ )

これは の perl スクリプトは、CPU 使用率を計算するためにすべてのフィールドを使用しますが、これもさらに調査した結果、正しいとは思えません。

カーネル コードにざっと目を通した後 ここで のように見えますが、例えば guest_niceguest fields と共に常に増加しています。 niceuser (に含まれているため、CPU使用率の計算には含まれないはずです)。 niceuser フィールドが既に存在します)

/*
 * Account guest cpu time to a process.
 * @p: the process that the cpu time gets accounted to
 * @cputime: the cpu time spent in virtual machine since the last update
 * @cputime_scaled: cputime scaled by cpu frequency
 */
static void account_guest_time(struct task_struct *p, cputime_t cputime,
                   cputime_t cputime_scaled)
{
    u64 *cpustat = kcpustat_this_cpu->cpustat;

    /* Add guest time to process. */
    p->utime += cputime;
    p->utimescaled += cputime_scaled;
    account_group_user_time(p, cputime);
    p->gtime += cputime;

    /* Add guest time to cpustat. */
    if (task_nice(p) > 0) {
        cpustat[CPUTIME_NICE] += (__force u64) cputime;
        cpustat[CPUTIME_GUEST_NICE] += (__force u64) cputime;
    } else {
        cpustat[CPUTIME_USER] += (__force u64) cputime;
        cpustat[CPUTIME_GUEST] += (__force u64) cputime;
    }
}

まとめると、LinuxでCPU使用率を計算する正確な方法は何か、またどのフィールドをどのように計算で考慮すべきか(どのフィールドがアイドル時間に、どのフィールドが非アイドル時間に帰着するか)?

どのように解決するのですか?

によると htop のソースコードによると、私の仮定は有効のようです。

(参照 static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) の関数を参照してください。 LinuxProcessList.c )

// Guest time is already accounted in usertime
usertime = usertime - guest;                             # As you see here, it subtracts guest from user time
nicetime = nicetime - guestnice;                         # and guest_nice from nice time
// Fields existing on kernels >= 2.6
// (and RHEL's patched kernel 2.4...)
unsigned long long int idlealltime = idletime + ioWait;  # ioWait is added in the idleTime
unsigned long long int systemalltime = systemtime + irq + softIrq;
unsigned long long int virtalltime = guest + guestnice;
unsigned long long int totaltime = usertime + nicetime + systemalltime + idlealltime + steal + virtalltime;

で、1行目にリストされたフィールドから /proc/stat : (1.8節参照 ドキュメント )

     user    nice   system  idle      iowait irq   softirq  steal  guest  guest_nice
cpu  74608   2520   24433   1117073   6176   4054  0        0      0      0

アルゴリズム的には、次のようにCPU使用率を計算することができます。

PrevIdle = previdle + previowait
Idle = idle + iowait

PrevNonIdle = prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevsteal
NonIdle = user + nice + system + irq + softirq + steal

PrevTotal = PrevIdle + PrevNonIdle
Total = Idle + NonIdle

# differentiate: actual value minus the previous one
totald = Total - PrevTotal
idled = Idle - PrevIdle

CPU_Percentage = (totald - idled)/totald