Mencuri: yang mencuri waktu prosesor dari mesin virtual



Hai Saya ingin memberi tahu dalam bahasa sederhana tentang mekanisme kemunculan mencuri di dalam mesin virtual dan tentang beberapa artefak yang tidak diketahui yang dapat kami temukan selama penelitiannya, di mana saya harus menyelam sebagai penasihat teknis platform cloud Mail.ru Cloud Solutions . Platform berjalan pada KVM.

Waktu mencuri CPU adalah waktu di mana mesin virtual tidak menerima sumber daya prosesor untuk pelaksanaannya. Waktu ini dianggap hanya dalam sistem operasi tamu di lingkungan virtualisasi. Alasan kemana sumber daya yang sangat dialokasikan ini pergi, seperti dalam kehidupan, sangat kabur. Tapi kami memutuskan untuk mencari tahu, bahkan membuat serangkaian percobaan. Bukannya kita sekarang tahu segalanya tentang mencuri, tetapi kami akan memberi tahu Anda sesuatu yang menarik saat ini.

1. Apa itu mencuri?


Jadi, mencuri adalah metrik yang menunjukkan kurangnya waktu prosesor untuk proses di dalam mesin virtual. Seperti yang dijelaskan dalam patch kernel KVM , mencuri adalah waktu di mana hypervisor mengeksekusi proses lain pada OS host, meskipun itu telah mengantri proses mesin virtual untuk dieksekusi. Artinya, mencuri dianggap sebagai perbedaan antara waktu ketika proses siap untuk dieksekusi dan waktu ketika prosesor dialokasikan waktu proses.

Kernel kernel menerima metrik mencuri dari hypervisor. Pada saat yang sama, hypervisor tidak menentukan dengan tepat proses apa yang dijalankannya, hanya "ketika saya sibuk, saya tidak bisa memberi Anda waktu." Di KVM, mencuri dukungan penghitungan telah ditambahkan di tambalan . Ada dua poin utama di sini:

  • Mesin virtual belajar tentang mencuri dari hypervisor. Yaitu, dari sudut pandang kerugian, untuk proses pada mesin virtual itu sendiri itu adalah pengukuran tidak langsung yang dapat dikenakan berbagai distorsi.
  • Hypervisor tidak berbagi informasi dengan mesin virtual tentang apa yang dia lakukan dengan orang lain - hal utama adalah dia tidak menyediakan waktu untuk itu. Karena itu, mesin virtual itu sendiri tidak dapat mendeteksi distorsi dalam indeks mencuri, yang dapat diperkirakan oleh sifat proses yang bersaing.

2. Apa yang mempengaruhi mencuri


2.1. Mencuri perhitungan


Bahkan, mencuri dianggap kurang lebih sama dengan waktu pemanfaatan CPU normal. Tidak ada banyak informasi tentang bagaimana pembuangan dipertimbangkan. Mungkin karena mayoritas menganggap pertanyaan ini jelas. Tapi ada juga jebakan di sini. Untuk berkenalan dengan proses ini, Anda dapat membaca artikel oleh Brendann Gregg : Anda akan belajar tentang banyak nuansa dalam perhitungan pemanfaatan dan tentang situasi ketika perhitungan ini akan keliru karena alasan berikut:

  • Prosesor terlalu panas, selama siklus clock dilewati.
  • Nyalakan / matikan turbo boost, sebagai akibatnya frekuensi clock prosesor berubah.
  • Perubahan durasi kuantum waktu yang terjadi saat menggunakan teknologi hemat energi prosesor, seperti SpeedStep.
  • Masalah penghitungan rata-rata: estimasi pemanfaatan dalam satu menit pada 80% dapat menyembunyikan ledakan jangka pendek dalam 100%.
  • Cyclic lock (spin lock) mengarah pada fakta bahwa prosesor dibuang, tetapi proses pengguna tidak melihat kemajuan dalam pelaksanaannya. Akibatnya, perkiraan pemanfaatan prosesor oleh proses akan seratus persen, meskipun proses tidak akan menghabiskan waktu prosesor secara fisik.

Saya tidak menemukan artikel yang menggambarkan perhitungan yang sama untuk mencuri (jika Anda tahu, bagikan dalam komentar). Tetapi, dilihat dari sumbernya, mekanisme perhitungannya sama dengan pembuangan. Hanya saja penghitung lain ditambahkan ke kernel, langsung untuk proses KVM (proses mesin virtual), yang menghitung lamanya waktu proses KVM dalam keadaan siaga waktu prosesor. Penghitung mengambil informasi tentang prosesor dari spesifikasinya dan mencari tahu apakah semua kutu telah digunakan oleh proses virtual. Jika itu saja, maka kami percaya bahwa prosesor hanya terlibat dalam proses mesin virtual. Kalau tidak, kami informasikan bahwa prosesor sedang melakukan sesuatu yang lain, mencuri muncul.

Proses mencuri mencuri memiliki masalah yang sama seperti menghitung daur ulang biasa. Bukan untuk mengatakan bahwa masalah seperti itu sering muncul, tetapi mereka terlihat mengecewakan.

2.2. Jenis Virtualisasi pada KVM


Secara umum, ada tiga jenis virtualisasi, dan semuanya didukung oleh KVM. Jenis virtualisasi dapat menentukan mekanisme mencuri.

Siaran Dalam hal ini, pengoperasian sistem operasi mesin virtual dengan perangkat fisik hypervisor terjadi kira-kira seperti ini:

  1. Sistem operasi tamu mengirimkan perintah ke perangkat tamunya.
  2. Driver perangkat tamu menerima perintah, menghasilkan permintaan untuk BIOS perangkat, dan mengirimkannya ke hypervisor.
  3. Proses hypervisor menerjemahkan perintah menjadi perintah untuk perangkat fisik, membuatnya, antara lain, lebih aman.
  4. Driver perangkat fisik menerima perintah yang dimodifikasi dan mengirimkannya ke perangkat fisik itu sendiri.
  5. Hasil eksekusi perintah kembali di jalur yang sama.

Keuntungan terjemahannya adalah memungkinkan Anda untuk meniru perangkat apa pun dan tidak memerlukan persiapan khusus dari kernel sistem operasi. Tetapi Anda harus membayar untuk itu, pertama-tama, dengan kecepatan.

Virtualisasi perangkat keras . Dalam hal ini, perangkat di tingkat perangkat keras memahami perintah dari sistem operasi. Ini adalah cara tercepat dan terbaik. Tetapi, sayangnya, itu tidak didukung oleh semua perangkat fisik, hypervisor, dan OS tamu. Saat ini, perangkat utama yang mendukung virtualisasi perangkat keras adalah prosesor.

Paravirtualization (paravirtualization) . Versi paling umum dari virtualisasi perangkat pada KVM dan umumnya mode virtualisasi yang paling umum untuk sistem operasi tamu. Kekhasannya adalah bahwa bekerja dengan beberapa subsistem hypervisor (misalnya, dengan jaringan atau tumpukan disk) atau alokasi halaman memori terjadi menggunakan API hypervisor, tanpa menerjemahkan perintah tingkat rendah. Kerugian dari metode virtualisasi ini adalah kebutuhan untuk memodifikasi kernel dari sistem operasi guest sehingga dapat berinteraksi dengan hypervisor menggunakan API ini. Tetapi biasanya ini diselesaikan dengan menginstal driver khusus pada sistem operasi tamu. Di KVM, API ini disebut virtio API .

Dengan paravirtualization, dibandingkan dengan terjemahan, jalur ke perangkat fisik berkurang secara signifikan dengan mengirimkan perintah langsung dari mesin virtual ke proses hypervisor host. Ini memungkinkan Anda untuk mempercepat pelaksanaan semua instruksi di dalam mesin virtual. Di KVM, virtio API bertanggung jawab untuk ini, yang hanya berfungsi untuk perangkat tertentu, seperti adaptor jaringan atau disk. Itulah sebabnya driver virtio ditempatkan di dalam mesin virtual.

Sisi lain dari akselerasi ini adalah bahwa tidak semua proses yang berjalan di dalam mesin virtual tetap berada di dalamnya. Ini menciptakan beberapa efek khusus yang dapat menyebabkan mencuri muncul. Saya sarankan memulai studi rinci tentang masalah ini dengan API untuk virtual I / O: virtio .

2.3. Penjadwalan yang Adil


Virtualisasi pada hypervisor sebenarnya adalah proses biasa yang mematuhi hukum penjadwalan (alokasi sumber daya antar proses) di kernel Linux, jadi kami akan mempertimbangkannya secara lebih rinci.

Linux menggunakan CFS, Completely Fair Scheduler, yang telah menjadi dispatcher default sejak kernel 2.6.23. Untuk memahami algoritma ini, Anda dapat membaca Arsitektur Kernel Linux atau sumber. Inti dari CFS adalah distribusi waktu prosesor antar proses tergantung pada durasi eksekusi mereka. Semakin banyak waktu prosesor yang dibutuhkan, semakin sedikit waktu yang diterimanya. Ini menjamin eksekusi "jujur" semua proses - sehingga satu proses tidak terus-menerus menempati semua prosesor, dan proses lainnya juga dapat dieksekusi.

Terkadang paradigma ini mengarah pada artefak yang menarik. Pengguna Linux yang sudah lama mungkin akan mengingat memudar dari editor teks desktop biasa saat menjalankan aplikasi seperti compiler. Ini terjadi karena tugas-tugas aplikasi desktop yang tidak memerlukan banyak sumber daya bersaing dengan tugas-tugas yang secara aktif mengonsumsi sumber daya, seperti penyusun. CFS menganggap ini tidak jujur, sehingga secara berkala menghentikan editor teks dan memungkinkan prosesor untuk memproses tugas-tugas kompiler. Ini diperbaiki menggunakan mekanisme sched_autogroup , tetapi banyak fitur lain dari distribusi waktu CPU antara tugas tetap. Sebenarnya, cerita ini bukan tentang seberapa buruk hal-hal yang ada dalam CFS, tetapi upaya untuk menarik perhatian pada kenyataan bahwa distribusi waktu prosesor yang โ€œjujurโ€ bukanlah tugas yang paling sepele.

Poin penting lainnya dalam sheduler adalah preemption. Ini diperlukan untuk mendorong proses kekek dari prosesor dan membiarkan orang lain bekerja. Proses pengasingan disebut pengalihan konteks, pengalihan konteks prosesor. Dalam hal ini, seluruh konteks tugas disimpan: keadaan tumpukan, register, dll., Setelah itu proses menunggu, dan yang lainnya mengambil tempatnya. Ini adalah operasi yang mahal untuk OS, dan jarang digunakan, tetapi pada kenyataannya tidak ada yang salah dengan itu. Pergantian konteks yang sering dapat mengindikasikan masalah pada OS, tetapi biasanya ini berlangsung terus menerus dan tidak menunjukkan apa-apa secara khusus.

Cerita yang begitu panjang diperlukan untuk menjelaskan satu fakta: semakin banyak sumber daya prosesor yang coba dikonsumsi oleh sheduler Linux yang jujur, semakin cepat akan dihentikan sehingga proses lain dapat bekerja juga. Apakah ini benar atau tidak adalah masalah yang kompleks, yang diselesaikan secara berbeda di bawah beban yang berbeda. Di Windows, hingga saat ini, sheduler difokuskan pada pemrosesan prioritas aplikasi desktop, karena proses latar belakang mana yang bisa hang. Sun Solaris memiliki lima kelas sheduler yang berbeda. Ketika mereka memulai virtualisasi, mereka menambahkan keenam, penjadwal berbagi yang Adil , karena lima sebelumnya bekerja dengan virtualisasi Solaris Zones tidak memadai. Saya merekomendasikan memulai studi terperinci tentang masalah ini dengan buku-buku seperti Solaris Internal: Solaris 10 dan OpenSolaris Kernel Architecture atau Memahami Kernel Linux .

2.4. Bagaimana cara memonitor mencuri?


Memantau mencuri di dalam mesin virtual, seperti metrik prosesor lainnya, sederhana: Anda dapat menggunakan segala cara untuk menghapus metrik prosesor. Yang utama adalah bahwa mesin virtual ada di Linux. Untuk beberapa alasan, Windows tidak memberikan informasi tersebut kepada penggunanya. :(


Output dari perintah teratas: detail beban prosesor, di kolom paling kanan - mencuri

Kesulitan muncul ketika mencoba untuk mendapatkan informasi ini dari hypervisor. Anda dapat mencoba memprediksi mencuri pada mesin host, misalnya, dengan parameter Load Average (LA) - nilai rata-rata jumlah proses yang menunggu dalam antrian untuk dieksekusi. Metodologi untuk menghitung parameter ini tidak sederhana, tetapi secara umum, jika LA, dinormalisasi dengan jumlah utas prosesor, lebih besar dari 1, ini menunjukkan bahwa server Linux agak kelebihan beban.

Apa semua proses ini menunggu? Jawaban yang jelas adalah prosesor. Tetapi jawabannya tidak sepenuhnya benar, karena kadang-kadang prosesor gratis, dan LA berguling. Ingat bagaimana NFS jatuh dan bagaimana LA tumbuh . Bisa kira-kira sama dengan disk, dan dengan perangkat input / output lainnya. Namun pada kenyataannya, proses dapat mengharapkan akhir dari setiap kunci, baik fisik, yang terkait dengan perangkat I / O, dan logis, seperti mutex. Ini juga termasuk kunci di tingkat perangkat keras (jawaban yang sama dari disk), atau logika (yang disebut penguncian primitif, yang mencakup banyak entitas, mutex adaptif dan spin, semaphore, variabel kondisi, kunci rw, kunci ipc ...).

Fitur lain dari LA adalah dianggap sebagai nilai rata-rata untuk sistem operasi. Misalnya, 100 proses bersaing untuk satu file, dan kemudian LA = 50. Nilai yang sedemikian besar, tampaknya, menunjukkan bahwa OS itu buruk. Tetapi untuk kode lain yang ditulis miring, ini bisa menjadi keadaan normal, meskipun faktanya itu buruk hanya untuknya, dan proses lain dalam sistem operasi tidak menderita.

Karena rata-rata ini (dan tidak kurang dari satu menit), menentukan sesuatu dengan indikator LA bukanlah tugas yang paling berterima kasih, dengan hasil yang sangat tidak pasti dalam kasus-kasus tertentu. Jika Anda mencoba untuk mengetahuinya, Anda akan menemukan bahwa hanya kasus yang paling sederhana yang dijelaskan dalam artikel Wikipedia dan sumber daya lain yang tersedia, tanpa penjelasan mendalam tentang prosesnya. Saya mengirim semua yang tertarik, sekali lagi, di sini, ke Brendann Gregg - lebih jauh di tautan. Kepada siapa kemalasan dalam bahasa Inggris adalah terjemahan dari artikel populernya tentang LA .

3. Efek khusus


Sekarang mari kita memikirkan kasus-kasus utama pencurian yang kita temui. Saya akan memberi tahu Anda bagaimana mereka mengikuti dari sebelumnya dan bagaimana mereka berhubungan dengan indikator pada hypervisor.

Daur ulang . Yang paling sederhana dan paling sering: hypervisor digunakan kembali. Memang, ada banyak menjalankan mesin virtual, konsumsi prosesor besar di dalamnya, banyak kompetisi, pemanfaatan LA lebih dari 1 (dinormalkan oleh utas prosesor). Di dalam semua virtualoks semuanya melambat. Mencuri yang ditransmisikan dari hypervisor juga berkembang, perlu untuk mendistribusikan kembali beban atau mematikan seseorang. Secara umum, semuanya logis dan dapat dimengerti.

Paravirtualization versus instance tunggal . Ada satu mesin virtual tunggal di hypervisor, ia mengkonsumsi sebagian kecil dari itu, tetapi memberikan beban besar pada input / output, misalnya, pada disk. Dan dari suatu tempat di dalamnya mencuri kecil muncul, hingga 10% (seperti yang ditunjukkan oleh beberapa percobaan).

Kasingnya menarik. Mencuri muncul di sini hanya karena kunci di tingkat driver paravirtualized. Interupsi dibuat di dalam mesin virtual, diproses oleh driver, dan pergi ke hypervisor. Karena pemrosesan terputus pada hypervisor untuk mesin virtual, sepertinya permintaan terkirim, siap untuk dieksekusi dan menunggu prosesor, tetapi mereka tidak memberikan waktu prosesor. Virtualka berpikir bahwa kali ini dicuri.

Ini terjadi ketika buffer dikirim, ia pergi ke ruang kernel dari hypervisor, dan kami mulai menunggunya. Meskipun, dari sudut pandang virtualka, ia harus segera kembali. Karena itu, menurut algoritma perhitungan mencuri, kali ini dianggap dicuri. Kemungkinan besar, dalam situasi ini mungkin ada mekanisme lain (misalnya, memproses beberapa panggilan sistem lainnya), tetapi mereka seharusnya tidak jauh berbeda.

Sheduler terhadap virtualoks yang sarat muatan . Ketika satu mesin virtual menderita mencuri lebih dari yang lain, itu terhubung tepat dengan sheduler. Semakin kuat proses memuat prosesor, semakin cepat sheduler akan mengeluarkannya, sehingga yang lain juga bisa bekerja. Jika mesin virtual menghabiskan sedikit, dia hampir tidak melihat mencuri: prosesnya jujur โ€‹โ€‹duduk dan menunggu, perlu memberinya lebih banyak waktu. Jika mesin virtual menghasilkan beban maksimum pada semua inti, sering dikeluarkan dari prosesor dan mencoba untuk tidak memberikan banyak waktu.

Lebih buruk lagi, ketika proses di dalam mesin virtual mencoba untuk mendapatkan lebih banyak prosesor, karena mereka tidak dapat mengatasi pemrosesan data. Kemudian sistem operasi pada hypervisor, karena optimasi yang jujur, akan memberikan waktu prosesor lebih sedikit. Proses ini berlangsung seperti longsoran salju, dan mencuri melompat ke surga, meskipun mesin virtual lain mungkin hampir tidak menyadarinya. Dan semakin banyak inti, semakin buruk mesin jatuh di bawah distribusi. Singkatnya, mesin virtual yang sarat muatan dengan banyak core paling menderita.

Rendah LA, tapi ada mencuri . Jika LA sekitar 0,7 (yaitu, hypervisor tampaknya kekurangan beban), tetapi mencuri diamati di dalam masing-masing mesin virtual:

  • Opsi yang dijelaskan di atas dengan paravirtualization. Mesin virtual dapat menerima metrik yang mengarah untuk mencuri, meskipun semuanya baik-baik saja dengan hypervisor. Menurut hasil percobaan kami, opsi mencuri seperti itu tidak melebihi 10% dan seharusnya tidak memiliki dampak signifikan pada kinerja aplikasi di dalam mesin virtual.
  • Parameter LA dianggap salah. Lebih tepatnya, pada setiap momen tertentu itu dianggap benar, tetapi ketika dirata-rata selama satu menit, ternyata diremehkan. Misalnya, jika satu mesin virtual mengkonsumsi semua prosesornya tepat setengah menit per sepertiga dari hypervisor, maka LA per menit akan menjadi 0,15 pada hypervisor; empat mesin virtual yang bekerja secara bersamaan akan memberikan 0,6. Dan fakta bahwa selama setengah menit pada masing-masing dari mereka ada mencuri liar di 25% di LA, tidak bisa lagi ditarik.
  • Sekali lagi, karena sheduler yang memutuskan bahwa seseorang makan terlalu banyak, dan biarkan yang ini menunggu. Sementara itu, saya beralih konteks, memproses interupsi dan melakukan hal-hal penting sistem lainnya. Akibatnya, beberapa mesin virtual tidak melihat masalah, sementara yang lain mengalami penurunan kinerja yang serius.

4. Distorsi lainnya


Ada jutaan alasan lain untuk mendistorsi kembalinya waktu prosesor pada mesin virtual. Sebagai contoh, hypertreading dan NUMA menambah kompleksitas pada perhitungan. Mereka benar-benar mengacaukan pilihan kernel untuk menjalankan proses, karena sheduler menggunakan koefisien - bobot, yang ketika berpindah konteks membuat perhitungan semakin sulit.

Ada distorsi karena teknologi seperti turbo boost atau, sebaliknya, mode hemat energi, yang ketika menghitung pemanfaatan dapat secara artifisial meningkatkan atau mengurangi frekuensi atau bahkan irisan waktu pada server. Menghidupkan turbo boost mengurangi kinerja satu thread prosesor karena peningkatan kinerja yang lain. Pada saat ini, informasi tentang frekuensi prosesor saat ini tidak ditransmisikan ke mesin virtual, dan ia percaya bahwa seseorang sedang mengikat waktunya (misalnya, ia meminta 2 GHz, tetapi menerima setengahnya).

Secara umum, bisa ada banyak penyebab distorsi. Dalam sistem tertentu, Anda mungkin menemukan sesuatu yang lain. Lebih baik memulai dengan buku-buku yang saya berikan tautannya di atas, dan mengambil statistik dari hypervisor dengan utilitas seperti perf, sysdig, systemtap, di mana ada lusinan .

5. Kesimpulan


  1. Sejumlah mencuri dapat terjadi karena paravirtualization, dan itu dapat dianggap normal. Di Internet mereka menulis bahwa nilai ini bisa 5-10%. Itu tergantung pada aplikasi di dalam mesin virtual dan pada jenis beban apa yang diletakkan pada perangkat fisiknya. Penting untuk memperhatikan bagaimana aplikasi di dalam mesin virtual rasakan.
  2. Rasio beban pada hypervisor dan mencuri di dalam mesin virtual tidak selalu saling berhubungan, kedua perkiraan pencurian dapat keliru dalam situasi tertentu pada beban yang berbeda.
  3. Penjadwal tidak suka proses yang banyak bertanya. Dia mencoba memberi lebih sedikit kepada mereka yang meminta lebih. Mesin virtual besar itu jahat.
  4. Mencuri kecil bisa menjadi norma tanpa paravirtualization (dengan mempertimbangkan beban di dalam mesin virtual, fitur dari beban tetangga, distribusi beban antara benang dan faktor lainnya).
  5. Jika Anda ingin mengetahui mencuri dalam sistem tertentu, Anda harus meriset berbagai opsi, mengumpulkan metrik, menganalisisnya dengan cermat, dan memikirkan cara mendistribusikan beban secara merata. Penyimpangan dimungkinkan dari setiap kasus, yang harus dikonfirmasi secara eksperimental atau dilihat di debugger kernel.

Source: https://habr.com/ru/post/id449316/


All Articles