GNU/Linux >> Belajar Linux >  >> Linux

Pemanfaatan CPU tinggi tetapi rata-rata beban rendah

Solusi 1:

Setidaknya di Linux, rata-rata beban dan penggunaan CPU sebenarnya adalah dua hal yang berbeda. Rata-rata beban adalah pengukuran berapa banyak tugas yang menunggu dalam antrian kernel run (bukan hanya waktu CPU tetapi juga aktivitas disk) selama periode waktu tertentu. Pemanfaatan CPU adalah ukuran seberapa sibuk CPU saat ini. Beban terbanyak yang dipatok oleh satu utas CPU pada 100% selama satu menit dapat "berkontribusi" pada rata-rata beban 1 menit adalah 1. CPU 4 inti dengan hyperthreading (8 inti virtual) semuanya pada 100% selama 1 menit akan berkontribusi 8 untuk rata-rata pemuatan 1 menit.

Sering kali kedua angka ini memiliki pola yang berkorelasi satu sama lain, tetapi Anda tidak dapat menganggapnya sama. Anda dapat memiliki beban tinggi dengan penggunaan CPU hampir 0% (seperti ketika Anda memiliki banyak data IO yang terjebak dalam keadaan menunggu) dan Anda dapat memiliki beban 1 dan 100% CPU, ketika Anda menjalankan satu proses berulir kemiringan penuh. Juga untuk waktu yang singkat Anda dapat melihat CPU mendekati 100% tetapi bebannya masih di bawah 1 karena metrik rata-rata belum "mengejar".

Saya telah melihat server memiliki beban lebih dari 15.000 (ya benar-benar itu bukan salah ketik) dan CPU% mendekati 0%. Itu terjadi karena saham Samba mengalami masalah dan banyak sekali klien mulai terjebak dalam status tunggu IO. Kemungkinannya adalah jika Anda melihat nomor beban tinggi biasa tanpa aktivitas CPU yang sesuai, Anda mengalami masalah penyimpanan. Pada mesin virtual, hal ini juga dapat berarti bahwa ada VM lain yang sangat bersaing untuk mendapatkan sumber daya penyimpanan di host VM yang sama.

Beban tinggi juga tidak selalu merupakan hal yang buruk, sebagian besar waktu itu hanya berarti sistem sedang digunakan untuk kapasitas penuhnya atau mungkin di luar kemampuannya untuk mengimbangi (jika jumlah beban lebih tinggi dari jumlah inti prosesor). Di tempat saya dulu menjadi sysadmin, mereka memiliki seseorang yang melihat rata-rata beban pada sistem utama mereka lebih dekat daripada Nagios. Ketika bebannya tinggi, mereka akan menelepon saya 24/7 lebih cepat dari yang bisa Anda katakan SMTP. Sebagian besar waktu sebenarnya tidak ada yang salah, tetapi mereka mengaitkan nomor muatan dengan sesuatu yang salah dan mengawasinya seperti elang. Setelah memeriksa, tanggapan saya biasanya sistem hanya melakukan tugasnya. Tentu saja ini adalah tempat yang sama di mana beban naik lebih dari 15.000 (meskipun bukan server yang sama) jadi terkadang itu berarti ada sesuatu yang salah. Anda harus mempertimbangkan tujuan sistem Anda. Jika ini adalah pekerja keras, maka perkirakan bebannya akan tinggi secara alami.

Solusi 2:

Beban adalah angka yang sangat menipu. Ambillah dengan sebutir garam.

Jika Anda menelurkan banyak tugas dalam urutan yang sangat cepat yang diselesaikan dengan sangat cepat, jumlah proses dalam antrean proses terlalu kecil untuk mendaftarkan bebannya (kernel menghitung beban sekali setiap lima detik).

Pertimbangkan contoh ini, di host saya yang memiliki 8 inti logis, skrip python ini akan mencatat penggunaan CPU yang besar di atas (sekitar 85%), namun hampir tidak ada beban.

import os, sys

while True:
  for j in range(8):
    parent = os.fork()
    if not parent:
      n = 0
      for i in range(10000):
        n += 1
      sys.exit(0)
  for j in range(8):
    os.wait()

Implementasi lain, yang ini menghindari wait dalam kelompok 8 (yang akan memiringkan tes). Di sini induk selalu berusaha untuk menjaga jumlah anak pada jumlah CPU yang aktif sehingga akan jauh lebih sibuk daripada metode pertama dan semoga lebih akurat.

/* Compile with flags -O0 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <err.h>
#include <errno.h>

#include <sys/signal.h>
#include <sys/types.h>
#include <sys/wait.h>

#define ITERATIONS 50000

int maxchild = 0;
volatile int numspawned = 0;

void childhandle(
    int signal)
{
  int stat;
  /* Handle all exited children, until none are left to handle */
  while (waitpid(-1, &stat, WNOHANG) > 0) {
    numspawned--;
  }
}

/* Stupid task for our children to do */
void do_task(
    void)
{
  int i,j;
  for (i=0; i < ITERATIONS; i++)
    j++;
  exit(0);
}

int main() {
  pid_t pid;

  struct sigaction act;
  sigset_t sigs, old;

  maxchild = sysconf(_SC_NPROCESSORS_ONLN);

  /* Setup child handler */
  memset(&act, 0, sizeof(act));
  act.sa_handler = childhandle;
  if (sigaction(SIGCHLD, &act, NULL) < 0)
    err(EXIT_FAILURE, "sigaction");

  /* Defer the sigchild signal */
  sigemptyset(&sigs);
  sigaddset(&sigs, SIGCHLD);
  if (sigprocmask(SIG_BLOCK, &sigs, &old) < 0)
    err(EXIT_FAILURE, "sigprocmask");

  /* Create processes, where our maxchild value is not met */
  while (1) {
    while (numspawned < maxchild) {
      pid = fork();
      if (pid < 0)
        err(EXIT_FAILURE, "fork");

      else if (pid == 0) /* child process */
        do_task();
      else               /* parent */
        numspawned++;
    }
    /* Atomically unblocks signal, handler then picks it up, reblocks on finish */
    if (sigsuspend(&old) < 0 && errno != EINTR)
      err(EXIT_FAILURE, "sigsuspend");
  }
}

Alasan perilaku ini adalah algoritme menghabiskan lebih banyak waktu untuk membuat proses anak daripada menjalankan tugas sebenarnya (dihitung hingga 10.000). Tugas yang belum dibuat tidak dapat diperhitungkan dalam status 'runnable', namun akan memakan waktu %sys pada CPU saat dijalankan.

Jadi, jawabannya bisa jadi dalam kasus Anda bahwa pekerjaan apa pun yang sedang dilakukan menghasilkan sejumlah besar tugas secara berurutan (utas, atau proses).

Solusi 3:

Jika rata-rata beban tidak meningkat banyak, itu hanya berarti bahwa spesifikasi perangkat keras Anda dan sifat tugas yang akan diproses menghasilkan throughput keseluruhan yang baik, menghindarinya tertumpuk dalam antrean tugas untuk beberapa waktu.

Jika ada fenomena pertentangan karena misalnya kompleksitas tugas rata-rata terlalu tinggi atau waktu pemrosesan rata-rata tugas membutuhkan terlalu banyak siklus CPU, maka ya, rata-rata beban akan meningkat.

PEMBARUAN :

Mungkin tidak jelas dalam jawaban asli saya, jadi saya mengklarifikasi sekarang :

Rumus perhitungan rata-rata beban yang tepat adalah :loadvg = tasks running + tasks waiting (for cores) + tasks blocked .

Anda pasti dapat memiliki throughput yang baik dan mendekati rata-rata beban 24 tetapi tanpa penalti pada waktu pemrosesan tugas. Di sisi lain, Anda juga dapat memiliki 2-4 tugas berkala yang tidak diselesaikan dengan cukup cepat, kemudian Anda akan melihat jumlah tugas yang menunggu (untuk siklus CPU) bertambah dan pada akhirnya Anda akan mencapai beban rata-rata yang tinggi. Hal lain yang dapat terjadi adalah memiliki tugas yang menjalankan operasi I/O sinkron yang luar biasa kemudian memblokir inti, menurunkan throughput dan membuat antrian tugas menunggu bertambah (dalam hal ini Anda dapat melihat iowait perubahan metrik)

Solusi 4:

Meskipun jawaban Matthew Ife sangat membantu dan mengarahkan kami ke arah yang benar, bukan itu yang menyebabkan perilaku dalam kasus kami. Dalam kasus kami, kami memiliki aplikasi Java multi-utas yang menggunakan kumpulan utas, mengapa tidak ada pekerjaan yang dilakukan untuk membuat tugas yang sebenarnya.

Namun, pekerjaan sebenarnya yang dilakukan utas berumur pendek dan termasuk menunggu IO atau menunggu sinkronisasi. Seperti yang disebutkan Matthew dalam jawabannya, rata-rata beban diambil sampelnya oleh OS, sehingga tugas yang berumur pendek dapat terlewatkan.

Saya membuat program Java yang mereproduksi perilaku tersebut. Kelas Java berikut menghasilkan utilisasi CPU sebesar 28% (650% ditumpuk) di salah satu server kami. Saat melakukan ini, rata-rata beban sekitar 1,3. Kuncinya di sini adalah sleep() di dalam utas, tanpanya perhitungan beban sudah benar.

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MultiThreadLoad {

    private ThreadPoolExecutor e = new ThreadPoolExecutor(200, 200, 0l, TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(1000), new ThreadPoolExecutor.CallerRunsPolicy());

    public void load() {
        while (true) {
            e.execute(new Runnable() {

                @Override
                public void run() {
                    sleep100Ms();
                    for (long i = 0; i < 5000000l; i++)
                        ;
                }

                private void sleep100Ms() {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
    }

    public static void main(String[] args) {
        new MultiThreadLoad().load();
    }

}

Singkatnya, teorinya adalah bahwa utas dalam aplikasi kita banyak menganggur dan kemudian melakukan pekerjaan berumur pendek, mengapa tugas tidak diambil sampelnya dengan benar oleh perhitungan rata-rata beban.

Solusi 5:

Beban rata-rata mencakup tugas yang diblokir pada disk IO, sehingga Anda dapat dengan mudah memiliki penggunaan cpu nol dan rata-rata beban 10 hanya dengan memiliki 10 tugas yang semuanya mencoba membaca dari disk yang sangat lambat. Oleh karena itu, biasanya server yang sibuk mulai meronta-ronta disk dan semua pencarian menyebabkan banyak tugas yang diblokir, menaikkan rata-rata beban, sementara penggunaan cpu turun, karena semua tugas diblokir pada disk.


Linux
  1. CPU tinggi yang disebabkan oleh Sophos di Windows

  2. Memecahkan masalah penggunaan CPU yang tinggi di Windows Server

  3. kipmi0 IPMI Kernel Helper 99% / 100% Penggunaan CPU Tinggi (Tapi Rata-rata Beban Rendah)

  1. Memahami rata-rata beban OS dan menjalankan antrian/antrian yang diblokir dalam hal pemanfaatan CPU di Linux

  2. Apa artinya memuat rata-rata di Unix/Linux?

  3. Beban cpu sistem tinggi (%sys), sistem terkunci

  1. Jenkins berjalan pada penggunaan CPU yang sangat tinggi

  2. Beban server tinggi, CPU menganggur. NFS penyebabnya?

  3. Apa arti 'bagus' pada grafik penggunaan CPU?