Penggunaan CPU tinggi tetapi rata-rata beban rendah

28

Kami mengalami perilaku aneh di mana kami melihat utilisasi CPU tinggi tetapi rata-rata beban cukup rendah.

Perilaku tersebut paling baik digambarkan oleh grafik berikut dari sistem pemantauan kami.

Penggunaan dan pemuatan CPU

Pada sekitar 11:57 pemanfaatan CPU meningkat dari 25% menjadi 75%. Rata-rata beban tidak berubah secara signifikan.

Kami menjalankan server dengan 12 core dengan masing-masing 2 hyper thread. OS melihat ini sebagai 24 CPU.

Data pemanfaatan CPU dikumpulkan dengan menjalankan /usr/bin/mpstat 60 1setiap menit. Data untuk allbaris dan %usrkolom ditunjukkan pada bagan di atas. Saya yakin ini memang menunjukkan rata-rata per data CPU, bukan pemanfaatan "ditumpuk". Sementara kami melihat utilisasi 75% dalam bagan, kami melihat proses yang menunjukkan untuk menggunakan sekitar 2000% "susun" CPU di top.

Angka rata-rata beban diambil dari /proc/loadavgsetiap menit.

uname -a memberi:

Linux ab04 2.6.32-279.el6.x86_64 #1 SMP Wed Jun 13 18:24:36 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux

Dist Linux adalah Red Hat Enterprise Linux Server release 6.3 (Santiago)

Kami menjalankan beberapa aplikasi web Java di bawah beban yang cukup berat pada mesin, pikir 100 permintaan / s per mesin.

Jika saya menginterpretasikan data penggunaan CPU dengan benar, ketika kami memiliki utilisasi CPU 75% itu berarti CPU kami menjalankan proses 75% dari waktu rata-rata. Namun, jika CPU kita sibuk 75% dari waktu, bukankah seharusnya kita melihat rata-rata beban yang lebih tinggi? Bagaimana mungkin CPU sibuk 75% sementara kami hanya memiliki 2-4 pekerjaan dalam antrian?

Apakah kita mengartikan data kita dengan benar? Apa yang dapat menyebabkan perilaku ini?

K Erlandsson
sumber
Apakah sistem pemantauan menunjukkan beban CPU yang dinormalisasi (load / #CPUs)? Linux Biasa Beban CPU sulit untuk dibandingkan lintas sistem dengan jumlah core / cpu yang berbeda sehingga beberapa alat menggunakan beban CPU yang dinormalisasi.
Brian
Apakah maksud Anda membagi setiap titik data dengan jumlah CPU? Ya loadavg / 24 dalam kasus kami? Saya dapat dengan mudah membuat bagan dari data jika itu membantu.
K Erlandsson
Saya menyarankan grafik Anda mungkin sudah menunjukkan itu.
Brian
Ah, maaf sudah salah paham. Itu akan menjadi penjelasan yang bagus, tapi sayangnya itu adalah rata-rata beban seluruh sistem yang ditampilkan. Saya baru saja memeriksa tiga.
K Erlandsson

Jawaban:

50

Setidaknya di Linux, rata-rata beban dan pemanfaatan CPU sebenarnya adalah dua hal yang berbeda. Load rata-rata adalah ukuran berapa banyak tugas yang menunggu dalam antrian run kernel (tidak hanya waktu CPU tetapi juga aktivitas disk) selama periode waktu tertentu. Pemanfaatan CPU adalah ukuran seberapa sibuk CPU saat ini. Beban terbanyak yang dipasangkan oleh thread CPU tunggal 100% selama satu menit dapat "berkontribusi" pada rata-rata beban 1 menit adalah 1. CPU 4 inti dengan hyperthreading (8 core virtual) semuanya pada 100% selama 1 menit akan berkontribusi 8 hingga rata-rata memuat 1 menit.

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

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

Beban tinggi juga tidak selalu merupakan hal yang buruk, sebagian besar waktu itu hanya berarti sistem sedang digunakan untuk kapasitas penuh atau mungkin di luar kemampuannya untuk menjaga (jika jumlah beban lebih tinggi dari jumlah inti prosesor). Di tempat saya dulu seorang sysadmin, mereka memiliki seseorang yang menonton rata-rata beban pada sistem utama mereka lebih dekat daripada yang dilakukan Nagios. Ketika bebannya tinggi, mereka akan memanggil saya 24/7 lebih cepat dari yang Anda bisa katakan SMTP. Sebagian besar waktu sebenarnya tidak ada yang salah, tetapi mereka menghubungkan nomor muat dengan sesuatu yang salah dan menontonnya seperti elang. Setelah memeriksa, respons saya biasanya bahwa sistem hanya melakukan pekerjaannya. Tentu saja ini adalah tempat yang sama di mana beban naik lebih dari 15.000 (bukan server yang sama) jadi kadang-kadang itu berarti ada sesuatu yang salah. Anda harus mempertimbangkan tujuan sistem Anda. Jika itu adalah pekerja keras, maka perkirakan bebannya akan tinggi secara alami.

deltaray
sumber
Bagaimana maksud Anda bahwa saya dapat memiliki beban CPU 1 dan 100% dengan proses berulir tunggal? Apa utas yang Anda bicarakan? Jika kita mempertimbangkan proses Java kita, mereka memiliki berton-ton thread, tetapi saya berada di bawah asumsi bahwa untaian diperlakukan sebagai proses dari perspektif OS (mereka memiliki PID yang terpisah di Linux setelah semua). Mungkinkah sehingga proses java multi-threaded tunggal hanya dihitung sebagai satu tugas dari perspektif rata-rata beban?
K Erlandsson
Saya baru saja melakukan tes saya sendiri, utas dalam proses Java berkontribusi terhadap rata-rata beban seolah-olah mereka memisahkan proses (yaitu kelas java yang menjalankan 10 utas dalam loop sibuk-tunggu memberi saya beban mendekati 10). Saya akan sangat menghargai klarifikasi tentang proses berulir yang Anda sebutkan di atas. Terima kasih!
K Erlandsson
Maksud saya jika Anda memiliki proses non-multithreading (yaitu, yang hanya menggunakan satu CPU pada suatu waktu). Misalnya jika Anda hanya menulis program C sederhana yang menjalankan loop sibuk, itu hanya satu utas berjalan dan hanya menggunakan 1 CPU pada suatu waktu.
deltaray
Semua informasi yang saya temukan mengatakan bahwa utas dihitung sebagai proses terpisah ketika dilihat dari kernel dan saat menghitung beban. Oleh karena itu saya gagal melihat bagaimana saya dapat memiliki proses multi-threaded pada kemiringan penuh menghasilkan 1 beban dan 100% CPU pada sistem multi-CPU. Bisakah Anda membantu saya memahami maksud Anda?
K Erlandsson
Bagi siapa pun yang mencari lebih detail: "Linux Load Averages: Solving the Mystery" oleh Brendan Gregg memiliki semua jawaban yang pernah saya butuhkan.
Nickolay
24

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

Jika Anda menelurkan banyak tugas dalam suksesi yang sangat cepat yang selesai dengan sangat cepat, jumlah proses dalam antrian run terlalu kecil untuk mendaftarkan beban untuk mereka (kernel menghitung beban sekali setiap lima detik).

Pertimbangkan contoh ini, pada host saya yang memiliki 8 core logis, skrip python ini akan mendaftarkan 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 hindari waitdalam kelompok 8 (yang akan memiringkan tes). Di sini orang tua selalu berusaha untuk menjaga jumlah anak pada jumlah CPU aktif sehingga akan jauh lebih sibuk daripada metode pertama dan mudah-mudahan 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 untuk perilaku ini adalah algoritma menghabiskan lebih banyak waktu untuk menciptakan proses anak daripada menjalankan tugas yang sebenarnya (menghitung hingga 10.000). Tugas-tugas yang belum dibuat tidak dapat dihitung sebagai status 'runnable', namun akan mengambil% sys pada waktu CPU saat mereka dilahirkan.

Jadi, jawabannya bisa benar-benar dalam kasus Anda bahwa pekerjaan apa pun yang dilakukan memunculkan sejumlah besar tugas dalam suksesi cepat (utas, atau proses).

Matthew Ife
sumber
Terima kasih atas sarannya. Bagan dalam pertanyaan saya menunjukkan% waktu pengguna (waktu sistem CPU dikecualikan, kami hanya melihat sedikit peningkatan dalam waktu sistem). Mungkinkah banyak tugas kecil menjadi penjelasan? Jika rata-rata beban diambil sampel setiap 5 detik, apakah data penggunaan CPU seperti yang diberikan oleh mpstat lebih sering diambil sampelnya?
K Erlandsson
Saya tidak terbiasa dengan bagaimana pengambilan sampel CPU dilakukan di sana. Jangan pernah baca sumber kernel tentang itu. Dalam contoh saya% usr adalah 70% + dan% sys adalah 15%.
Matthew Ife
Contoh yang bagus!
Xavier Lucas
5

Jika rata-rata beban tidak bertambah banyak, itu hanya berarti bahwa spesifikasi perangkat keras Anda dan sifat tugas yang akan diproses menghasilkan throughput keseluruhan yang baik, sehingga tidak perlu ditumpuk dalam antrian tugas untuk beberapa waktu.

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

PEMBARUAN:

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

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

Anda pasti dapat memiliki throughput yang baik dan mendekati rata-rata muatan 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, maka Anda akan melihat jumlah tugas yang menunggu (untuk siklus CPU) tumbuh dan Anda akhirnya akan mencapai rata-rata beban yang tinggi. Hal lain yang dapat terjadi adalah memiliki tugas menjalankan operasi I / O sinkron yang luar biasa kemudian memblokir inti, menurunkan throughput dan membuat antrian tugas tunggu bertambah (dalam hal ini Anda mungkin melihat iowaitmetrik berubah)

Xavier Lucas
sumber
Ini adalah pemahaman saya bahwa rata-rata memuat juga mencakup tugas yang sedang dijalankan. Itu berarti kita pasti dapat memiliki peningkatan rata-rata beban tanpa pertentangan aktual untuk CPU. Atau saya salah paham?
K Erlandsson
@KristofferE Anda sepenuhnya benar. Rumus sebenarnya adalah loadavg = taks berjalan + tugas menunggu (untuk core yang tersedia) + tugas diblokir. Ini berarti Anda dapat memiliki rata-rata beban 24, tidak ada tugas menunggu atau diblokir, sehingga hanya memiliki "penggunaan penuh" atau kapasitas perangkat keras Anda tanpa pertentangan. Ketika Anda tampak bingung tentang rata-rata beban vs jumlah proses yang berjalan vs penggunaan CPU, saya terutama memfokuskan jawaban saya pada penjelasan tentang bagaimana rata-rata beban masih dapat tumbuh dengan begitu sedikit proses yang berjalan secara keseluruhan. Mungkin tidak terlalu jelas setelah membacanya kembali.
Xavier Lucas
2

Memuat rata-rata termasuk tugas yang diblokir pada disk IO, sehingga Anda dapat dengan mudah memiliki utilisasi cpu nol dan rata-rata beban 10 hanya dengan memiliki 10 tugas semua mencoba membaca dari disk yang sangat lambat. Oleh karena itu adalah hal yang biasa bagi server yang sibuk untuk 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.

psusi
sumber
1

Sementara jawaban Matthew Ife sangat membantu dan membawa kami ke arah yang benar, itu bukanlah penyebab perilaku kami. Dalam kasus kami, kami memiliki aplikasi Java multi-ulir yang menggunakan penggabungan ulir, mengapa tidak ada pekerjaan yang dilakukan untuk membuat tugas aktual.

Namun, pekerjaan aktual yang dilakukan thread hanya berumur pendek dan mencakup IO menunggu atau menunggu sinkronisasi. Seperti yang disebutkan Matius dalam jawabannya, rata-rata beban diambil oleh OS, dengan demikian tugas yang singkat dapat dilewatkan.

Saya membuat program Java yang mereproduksi perilaku. Kelas Java berikut menghasilkan utilisasi CPU 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, tanpa itu 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();
    }

}

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

K Erlandsson
sumber
0

Rata-rata beban adalah jumlah rata-rata proses dalam antrian CPU. Ini spesifik untuk setiap sistem, Anda tidak bisa mengatakan bahwa satu LA secara umum tinggi pada semua sistem, dan yang lain rendah. Jadi Anda memiliki 12 core, dan agar LA meningkat secara signifikan jumlah proses harus sangat tinggi.

Pertanyaan lain adalah apa yang dimaksud dengan grafik "Penggunaan CPU". Jika itu diambil dari SNMP, seperti seharusnya, dan implementasi SNMP Anda net-snmp, maka hanya tumpukan CPU-load dari masing-masing 12 CPU Anda. Jadi untuk net-snmpjumlah total beban CPU adalah 1200%.

Jika asumsi saya benar, maka penggunaan CPU tidak meningkat secara signifikan. Dengan demikian, LA tidak meningkat secara signifikan.

drookie
sumber
Penggunaan cpu diambil dari mpstat, allbaris. Saya cukup yakin itu adalah rata-rata di semua CPU, tidak ditumpuk. Misalnya, ketika masalah terjadi, atas menunjukkan penggunaan CPU 2000% untuk satu proses. Itu adalah penggunaan yang ditumpuk.
K Erlandsson
0

Skenario di sini tidak terlalu terduga meskipun sedikit tidak biasa. Apa yang disentuh Xavier, tetapi tidak berkembang banyak, adalah bahwa meskipun Linux (secara default) dan sebagian besar rasa Unix menerapkan multi-tasking pre-emptive, pada mesin yang sehat, tugas-tugas jarang akan menjadi pre-empted. Setiap tugas memiliki irisan waktu untuk menduduki CPU, itu hanya pre-empted jika melebihi waktu ini dan ada tugas-tugas lain yang menunggu untuk dijalankan (perhatikan bahwa memuat melaporkan jumlah rata-rata proses baik di CPU dan menunggu untuk berjalan) . Sebagian besar waktu, suatu proses akan menghasilkan daripada terputus.

(secara umum Anda hanya perlu khawatir tentang memuat ketika mendekati jumlah CPU - yaitu ketika scheduler memulai tugas pre-empting).

jika CPU kita sibuk 75% dari waktu, bukankah seharusnya kita melihat rata-rata beban yang lebih tinggi?

Semuanya tentang pola aktivitas, jelas meningkatkan pemanfaatan CPU oleh beberapa tugas (kemungkinan besar mintority kecil) tidak memiliki efek buruk pada pemrosesan tugas-tugas lain. Jika Anda dapat mengisolasi transaksi yang sedang diproses, saya berharap Anda akan melihat grup baru muncul selama perlambatan, sementara set tugas yang masih ada tidak terpengaruh.

memperbarui

Satu skenario umum di mana CPU tinggi dapat terjadi tanpa peningkatan beban yang besar adalah ketika tugas memicu satu (atau urutan) tugas lain, misalnya saat menerima permintaan jaringan, pawang mengarahkan permintaan ke utas terpisah, utas terpisah kemudian membuat beberapa panggilan tidak sinkron ke proses lain .... pengambilan sampel runqueue menyebabkan beban dilaporkan lebih rendah dari yang sebenarnya - tetapi tidak naik secara linear dengan penggunaan CPU - rantai tugas yang dipicu tidak akan dapat dijalankan tanpa adanya acara awal, dan karena mereka terjadi (lebih atau kurang) secara berurutan antrian run tidak meningkat.

symcbean
sumber
OP awalnya memberikan indikasi bahwa% CPU agregat adalah "2000%" menunjukkan ada banyak tugas menggunakan CPU, daripada hanya 1 proses sibuk. Jika konsisten 2000% selama satu menit, Anda biasanya akan mengantisipasi beban menjadi 20-ish.
Matthew Ife
... dalam komentar, tidak dalam pertanyaan, dan dia tidak begitu yakin tentang itu. Dengan tidak adanya opsi 'ALL', mpstat melaporkan total% penggunaan bukan rata-rata. Tapi itu tidak mengubah jawabannya - ini tentang pola aktivitas.
symcbean
Saya 100% positif bahwa util CPU yang kami lihat di grafik adalah "rata-rata per CPU". Mpstat dijalankan tanpa SEMUA, tetapi hanya menyisakan info per-CPU, allbaris tersebut tetap menunjukkan rata-rata per CPU. Saya akan mengklarifikasi pertanyaannya.
K Erlandsson
Bisakah Anda menjelaskan sedikit tentang bagian terakhir? Saya gagal memahami apa yang Anda maksud, sementara bagian dari pertanyaan saya yang Anda kutip adalah bagian yang paling sulit saya pahami.
K Erlandsson