Mencuri: siapa yang mencuri masa CPU daripada mesin maya

Mencuri: siapa yang mencuri masa CPU daripada mesin maya

hello! Saya ingin memberitahu anda secara ringkas tentang mekanik mencuri di dalam mesin maya dan tentang beberapa artifak yang tidak jelas yang kami berjaya ketahui semasa penyelidikannya, yang perlu saya selami sebagai pengarah teknikal platform awan Penyelesaian Awan Mail.ru. Platform ini berjalan pada KVM.

Masa mencuri CPU ialah masa di mana mesin maya tidak menerima sumber pemproses untuk pelaksanaannya. Masa ini hanya dikira dalam sistem pengendalian tetamu dalam persekitaran virtualisasi. Sebab-sebab ke mana sumber yang paling banyak diperuntukkan ini pergi, seperti dalam kehidupan, sangat samar-samar. Tetapi kami memutuskan untuk memikirkannya, dan juga menjalankan beberapa eksperimen. Bukannya kami kini tahu segala-galanya tentang mencuri, tetapi kami akan memberitahu anda sesuatu yang menarik sekarang.

1. Apa itu mencuri

Jadi, mencuri ialah metrik yang menunjukkan kekurangan masa pemproses untuk proses di dalam mesin maya. Seperti yang diterangkan dalam tampung kernel KVMStealth ialah masa semasa hypervisor melaksanakan proses lain pada OS hos walaupun ia telah beratur dalam proses mesin maya untuk pelaksanaan. Iaitu, mencuri dikira sebagai perbezaan antara masa apabila proses sedia untuk dilaksanakan dan masa apabila proses diperuntukkan masa pemproses.

Kernel mesin maya menerima metrik curi daripada hypervisor. Pada masa yang sama, hipervisor tidak menyatakan dengan tepat proses lain yang sedang dijalankan, ia hanya mengatakan "semasa saya sibuk, saya tidak dapat memberi anda masa." Pada KVM, sokongan untuk pengiraan mencuri telah ditambahkan pada tompok. Terdapat dua perkara penting di sini:

  • Mesin maya belajar tentang mencuri daripada hypervisor. Iaitu, dari sudut pandangan kerugian, untuk proses pada mesin maya itu sendiri ini adalah ukuran tidak langsung yang boleh tertakluk kepada pelbagai herotan.
  • Hypervisor tidak berkongsi maklumat dengan mesin maya tentang perkara lain yang sedang dilakukannya - perkara utama ialah ia tidak menumpukan masa kepadanya. Oleh sebab itu, mesin maya itu sendiri tidak dapat mengesan herotan dalam penunjuk curi, yang boleh dinilai oleh sifat proses bersaing.

2. Apa yang menjejaskan mencuri

2.1. Curi pengiraan

Pada asasnya, mencuri dikira lebih kurang sama dengan masa penggunaan CPU biasa. Tidak banyak maklumat tentang cara kitar semula dipertimbangkan. Mungkin kerana kebanyakan orang menganggap soalan ini jelas. Tetapi terdapat juga perangkap di sini. Untuk membiasakan diri dengan proses ini, anda boleh membaca artikel oleh Brendan Gregg: anda akan belajar tentang banyak nuansa semasa mengira penggunaan dan tentang situasi apabila pengiraan ini akan tersilap atas sebab-sebab berikut:

  • Pemproses menjadi terlalu panas, menyebabkan kitaran melangkau.
  • Dayakan/lumpuhkan rangsangan turbo, yang mengubah kelajuan jam pemproses.
  • Perubahan dalam tempoh potongan masa yang berlaku apabila menggunakan teknologi penjimatan kuasa pemproses seperti SpeedStep.
  • Masalah dengan mengira purata: menganggarkan penggunaan satu minit pada 80% boleh menyembunyikan pecahan jangka pendek sebanyak 100%.
  • Kunci putaran menyebabkan pemproses dituntut semula, tetapi proses pengguna tidak melihat sebarang kemajuan dalam pelaksanaannya. Akibatnya, penggunaan pemproses yang dikira oleh proses akan menjadi seratus peratus, walaupun proses itu tidak akan memakan masa pemproses secara fizikal.

Saya tidak menemui artikel yang menerangkan pengiraan yang sama untuk mencuri (jika anda tahu, kongsikannya dalam ulasan). Tetapi, berdasarkan kod sumber, mekanisme pengiraan adalah sama seperti untuk kitar semula. Secara mudah, kaunter lain ditambahkan dalam kernel, terus untuk proses KVM (proses mesin maya), yang mengira tempoh proses KVM menunggu masa CPU. Kaunter mengambil maklumat tentang pemproses daripada spesifikasinya dan menyemak sama ada semua kutunya digunakan oleh proses mesin maya. Jika itu sahaja, maka kami menganggap bahawa pemproses hanya sibuk dengan proses mesin maya. Jika tidak, kami memaklumkan bahawa pemproses sedang melakukan sesuatu yang lain, mencuri muncul.

Proses pengiraan curi tertakluk kepada masalah yang sama seperti pengiraan kitar semula biasa. Bukan untuk mengatakan bahawa masalah sedemikian sering muncul, tetapi ia kelihatan mengecewakan.

2.2. Jenis virtualisasi pada KVM

Secara umum, terdapat tiga jenis virtualisasi, semuanya disokong oleh KVM. Mekanisme kejadian mencuri mungkin bergantung pada jenis virtualisasi.

Siaran. Dalam kes ini, pengendalian sistem pengendalian mesin maya dengan peranti hypervisor fizikal berlaku seperti ini:

  1. Sistem pengendalian tetamu menghantar arahan ke peranti tetamunya.
  2. Pemacu peranti tetamu menerima arahan, menjana permintaan untuk BIOS peranti dan menghantarnya kepada hipervisor.
  3. Proses hipervisor menterjemah perintah kepada perintah untuk peranti fizikal, menjadikannya, antara lain, lebih selamat.
  4. Pemacu peranti fizikal menerima arahan yang diubah suai dan menghantarnya ke peranti fizikal itu sendiri.
  5. Hasil daripada melaksanakan arahan kembali di sepanjang laluan yang sama.

Kelebihan terjemahan ialah ia membolehkan anda meniru mana-mana peranti dan tidak memerlukan penyediaan khas kernel sistem pengendalian. Tetapi anda perlu membayar untuk ini, pertama sekali, dalam kelajuan.

Virtualisasi perkakasan. Dalam kes ini, peranti di peringkat perkakasan memahami arahan daripada sistem pengendalian. Ini adalah cara terpantas dan terbaik. Tetapi, malangnya, ia tidak disokong oleh semua peranti fizikal, hipervisor dan sistem pengendalian tetamu. Pada masa ini, peranti utama yang menyokong virtualisasi perkakasan ialah pemproses.

Paravirtualisasi. Pilihan yang paling biasa untuk virtualisasi peranti pada KVM dan secara amnya mod virtualisasi yang paling biasa untuk sistem pengendalian tetamu. Keanehannya ialah kerja dengan beberapa subsistem hipervisor (contohnya, dengan rangkaian atau timbunan cakera) atau peruntukan halaman memori berlaku menggunakan API hipervisor, tanpa menterjemah arahan peringkat rendah. Kelemahan kaedah virtualisasi ini ialah kernel sistem pengendalian tetamu mesti diubah suai supaya ia boleh berkomunikasi dengan hypervisor menggunakan API ini. Tetapi ini biasanya diselesaikan dengan memasang pemacu khas pada sistem pengendalian tetamu. Dalam KVM API ini dipanggil API virtio.

Dengan paravirtualisasi, berbanding dengan penyiaran, laluan ke peranti fizikal dikurangkan dengan ketara dengan menghantar arahan terus dari mesin maya ke proses hypervisor pada hos. Ini membolehkan anda mempercepatkan pelaksanaan semua arahan di dalam mesin maya. Dalam KVM, ini dilakukan oleh API virtio, yang hanya berfungsi untuk peranti tertentu, seperti rangkaian atau penyesuai cakera. Inilah sebabnya pemacu virtio dipasang di dalam mesin maya.

Kelemahan pecutan ini ialah tidak semua proses yang berjalan di dalam mesin maya kekal di dalamnya. Ini mencipta beberapa kesan khas yang boleh mengakibatkan pemijahan pada mencuri. Saya mengesyorkan memulakan kajian terperinci tentang isu ini dengan API untuk I/O maya: virtio.

2.3. Penjadualan "adil".

Mesin maya pada hypervisor, sebenarnya, proses biasa yang mematuhi undang-undang penjadualan (pengagihan sumber antara proses) dalam kernel Linux, jadi mari kita lihat dengan lebih dekat.

Linux menggunakan apa yang dipanggil CFS, Completely Fair Scheduler, yang telah menjadi penjadual lalai sejak kernel 2.6.23. Untuk memahami algoritma ini, anda boleh membaca Seni Bina Kernel Linux atau kod sumber. Intipati CFS adalah untuk mengagihkan masa pemproses antara proses bergantung pada tempoh pelaksanaannya. Semakin banyak masa CPU yang diperlukan oleh proses, semakin sedikit masa CPU yang diterima. Ini memastikan bahawa semua proses dilaksanakan "secara adil" - supaya satu proses tidak sentiasa menduduki semua pemproses, dan proses lain juga boleh dilaksanakan.

Kadangkala paradigma ini membawa kepada artifak yang menarik. Pengguna Linux lama mungkin mengingati pembekuan editor teks biasa pada desktop semasa menjalankan aplikasi intensif sumber seperti pengkompil. Ini berlaku kerana tugas tidak intensif sumber dalam aplikasi desktop bersaing dengan tugas intensif sumber, seperti pengkompil. CFS berpendapat ini tidak adil, jadi ia menghentikan editor teks secara berkala dan membenarkan pemproses mengendalikan tugas pengkompil. Ini telah diperbetulkan menggunakan mekanisme sched_autogroup, tetapi banyak ciri lain pengagihan masa pemproses antara tugas kekal. Sebenarnya, ini bukan cerita tentang betapa buruknya segala-galanya dalam CFS, tetapi percubaan untuk menarik perhatian kepada fakta bahawa pengagihan masa pemproses yang "adil" bukanlah tugas yang paling remeh.

Satu lagi perkara penting dalam penjadual ialah preemption. Ini adalah perlu untuk menghentikan proses ketawa daripada pemproses dan membiarkan orang lain bekerja. Proses ejection dipanggil context switching. Dalam kes ini, keseluruhan konteks tugas itu dipelihara: keadaan timbunan, daftar, dsb., selepas itu proses dihantar untuk menunggu, dan satu lagi mengambil tempatnya. Ini adalah operasi yang mahal untuk OS dan jarang digunakan, tetapi tidak ada yang salah dengannya. Penukaran konteks yang kerap mungkin menunjukkan masalah dalam OS, tetapi biasanya ia berterusan dan tidak menunjukkan apa-apa secara khusus.

Cerita yang begitu panjang diperlukan untuk menjelaskan satu fakta: lebih banyak sumber pemproses cuba digunakan dalam penjadual Linux yang jujur, lebih cepat ia akan dihentikan supaya proses lain juga boleh berfungsi. Sama ada ini betul atau tidak adalah persoalan kompleks yang boleh diselesaikan secara berbeza di bawah beban yang berbeza. Di Windows, sehingga baru-baru ini, penjadual tertumpu pada pemprosesan keutamaan aplikasi desktop, yang boleh menyebabkan proses latar belakang menjadi beku. Sun Solaris mempunyai lima kelas penjadual yang berbeza. Apabila kami melancarkan virtualisasi, kami menambah yang keenam, Penjadual bahagian saksama, kerana lima sebelumnya tidak berfungsi dengan baik dengan virtualisasi Zon Solaris. Saya mengesyorkan memulakan kajian terperinci tentang isu ini dengan buku seperti Solaris Internals: Solaris 10 dan OpenSolaris Kernel Architecture atau Memahami Kernel Linux.

2.4. Bagaimana untuk memantau mencuri?

Pemantauan mencuri di dalam mesin maya, seperti mana-mana metrik pemproses lain, adalah mudah: anda boleh menggunakan sebarang alat metrik pemproses. Perkara utama ialah mesin maya berada di Linux. Atas sebab tertentu Windows tidak memberikan maklumat ini kepada penggunanya. πŸ™

Mencuri: siapa yang mencuri masa CPU daripada mesin maya
Output arahan atas: butiran beban pemproses, di lajur paling kanan - mencuri

Kesukaran timbul apabila cuba mendapatkan maklumat ini daripada hypervisor. Anda boleh cuba meramalkan mencuri pada mesin hos, contohnya, menggunakan parameter Purata Beban (LA) - nilai purata bilangan proses yang menunggu dalam baris gilir pelaksanaan. Kaedah untuk mengira parameter ini tidak mudah, tetapi secara amnya, jika LA dinormalkan dengan bilangan utas pemproses adalah lebih daripada 1, ini menunjukkan bahawa pelayan Linux terlalu sarat dengan sesuatu.

Apakah semua proses ini menunggu? Jawapan yang jelas ialah pemproses. Tetapi jawapannya tidak sepenuhnya betul, kerana kadang-kadang pemproses adalah percuma, tetapi LA tidak berskala. Ingat bagaimana NFS jatuh dan bagaimana LA berkembang. Perkara yang sama boleh berlaku dengan cakera dan peranti input/output lain. Tetapi sebenarnya, proses boleh menunggu penghujung sebarang kunci, sama ada fizikal, yang dikaitkan dengan peranti I/O, atau logik, seperti mutex. Ini juga termasuk penguncian pada tahap perkakasan (tindak balas yang sama daripada cakera), atau logik (yang dipanggil primitif penguncian, yang merangkumi sekumpulan entiti, penyesuaian dan putaran mutex, semaphore, pembolehubah keadaan, kunci rw, kunci ipc ...).

Satu lagi ciri LA ialah ia dianggap sebagai purata sistem pengendalian. Sebagai contoh, 100 proses bersaing untuk satu fail, dan kemudian LA=50. Nilai yang begitu besar nampaknya menunjukkan bahawa sistem pengendalian itu buruk. Tetapi untuk kod lain yang ditulis secara bengkok, ini mungkin keadaan biasa, walaupun pada hakikatnya ia adalah buruk, dan proses lain dalam sistem pengendalian tidak terjejas.

Oleh kerana purata ini (dan dalam masa tidak kurang daripada satu minit), menentukan apa-apa dengan penunjuk LA bukanlah tugas yang paling menggembirakan, dengan keputusan yang sangat tidak pasti dalam kes tertentu. Jika anda cuba memikirkannya, anda akan mendapati bahawa artikel di Wikipedia dan sumber lain yang tersedia hanya menerangkan kes yang paling mudah, tanpa penjelasan yang mendalam tentang proses tersebut. Saya menghantar semua orang yang berminat, sekali lagi, di sini kepada Brendan Gregg  - ikuti pautan di bawah. Siapa yang malas bercakap bahasa Inggeris - terjemahan artikel popularnya tentang LA.

3. Kesan khas

Sekarang mari kita lihat kes-kes utama mencuri yang kita hadapi. Saya akan memberitahu anda cara mereka mengikuti daripada semua perkara di atas dan bagaimana ia berkaitan dengan penunjuk pada hipervisor.

Kitar semula. Yang paling mudah dan paling biasa: hypervisor telah digunakan semula. Sesungguhnya, terdapat banyak mesin maya yang sedang berjalan, penggunaan pemproses yang tinggi di dalamnya, banyak persaingan, penggunaan LA adalah lebih daripada 1 (dinormalkan oleh benang pemproses). Segala-galanya di dalam semua mesin maya menjadi perlahan. Curi yang dihantar dari hypervisor juga semakin meningkat, adalah perlu untuk mengagihkan semula beban atau mematikan seseorang. Secara umum, semuanya adalah logik dan boleh difahami.

Paravirtualisasi lwn. Kejadian Tunggal. Hanya terdapat satu mesin maya pada hypervisor; ia menggunakan sebahagian kecil daripadanya, tetapi menghasilkan beban I/O yang besar, contohnya pada cakera. Dan dari suatu tempat mencuri kecil muncul di dalamnya, sehingga 10% (seperti yang ditunjukkan oleh beberapa eksperimen).

Kes itu menarik. Mencuri muncul di sini tepat kerana menyekat pada tahap pemandu paravirtual. Gangguan dibuat di dalam mesin maya, diproses oleh pemandu dan dihantar kepada hipervisor. Oleh kerana pengendalian gangguan pada hypervisor, untuk mesin maya ia kelihatan seperti permintaan yang dihantar, ia sedia untuk dilaksanakan dan sedang menunggu pemproses, tetapi ia tidak diberikan masa pemproses. Gadis maya itu menyangka bahawa kali ini telah dicuri.

Ini berlaku pada masa penimbal dihantar, ia masuk ke ruang kernel hipervisor, dan kami mula menunggunya. Walaupun, dari sudut pandangan mesin maya, dia harus segera kembali. Oleh itu, mengikut algoritma pengiraan mencuri, kali ini dianggap dicuri. Kemungkinan besar, dalam situasi ini mungkin terdapat mekanisme lain (contohnya, memproses beberapa panggilan sys lain), tetapi mereka tidak sepatutnya berbeza.

Penjadual berbanding mesin maya yang sangat dimuatkan. Apabila satu mesin maya menderita daripada mencuri lebih daripada yang lain, ini disebabkan oleh penjadual. Lebih banyak proses memuatkan pemproses, lebih cepat penjadual akan menendangnya supaya yang lain juga boleh berfungsi. Jika mesin maya menggunakan sedikit, ia tidak akan melihat mencuri: prosesnya dengan jujur ​​duduk dan menunggu, kita perlu memberi lebih banyak masa. Jika mesin maya menghasilkan beban maksimum pada semua terasnya, ia sering ditendang keluar daripada pemproses dan mereka cuba untuk tidak memberikannya banyak masa.

Lebih teruk lagi apabila proses di dalam mesin maya cuba mendapatkan lebih banyak pemproses kerana mereka tidak dapat mengatasi pemprosesan data. Kemudian sistem pengendalian pada hypervisor, disebabkan pengoptimuman yang jujur, akan memberikan masa pemproses yang semakin kurang. Proses ini berlaku seperti runtuhan salji, dan mencuri melompat ke langit, walaupun mesin maya lain mungkin tidak menyedarinya. Dan lebih banyak teras, lebih teruk mesin yang terjejas. Pendek kata, mesin maya yang sarat tinggi dengan banyak teras paling menderita.

LA rendah, tetapi ada mencuri. Jika LA adalah lebih kurang 0,7 (iaitu, hypervisor nampaknya kurang dimuatkan), tetapi mencuri diperhatikan di dalam mesin maya individu:

  • Pilihan dengan paravirtualisasi telah diterangkan di atas. Mesin maya boleh menerima metrik yang menunjukkan mencuri, walaupun hipervisor baik. Mengikut keputusan percubaan kami, pilihan mencuri ini tidak melebihi 10% dan tidak sepatutnya memberi kesan yang ketara terhadap prestasi aplikasi di dalam mesin maya.
  • Parameter LA dikira secara salah. Lebih tepat lagi, pada setiap saat tertentu ia dikira dengan betul, tetapi apabila dipuratakan selama satu minit ia ternyata dipandang remeh. Sebagai contoh, jika satu mesin maya setiap pertiga daripada hypervisor menggunakan semua pemprosesnya selama setengah minit, maka LA seminit pada hypervisor ialah 0,15; empat mesin maya sedemikian yang berfungsi serentak akan memberikan 0,6. Dan hakikat bahawa selama setengah minit pada setiap daripada mereka terdapat mencuri liar pada 25% mengikut penunjuk LA tidak boleh ditarik keluar lagi.
  • Sekali lagi, kerana penjadual yang memutuskan bahawa seseorang makan terlalu banyak dan membiarkan seseorang itu menunggu. Sementara itu, saya akan menukar konteks, mengendalikan gangguan dan mengurus perkara penting sistem yang lain. Akibatnya, sesetengah mesin maya tidak melihat sebarang masalah, manakala yang lain mengalami kemerosotan prestasi yang serius.

4. Herotan lain

Terdapat sejuta lagi sebab untuk memutarbelitkan pulangan adil masa pemproses pada mesin maya. Contohnya, hyperthreading dan NUMA memperkenalkan kesukaran ke dalam pengiraan. Mereka mengelirukan sepenuhnya pilihan kernel untuk melaksanakan proses, kerana penjadual menggunakan pekali - pemberat, yang menjadikan pengiraan lebih sukar apabila menukar konteks.

Terdapat herotan disebabkan oleh teknologi seperti rangsangan turbo atau, sebaliknya, mod penjimatan tenaga, yang, apabila mengira penggunaan, boleh menambah atau mengurangkan frekuensi secara buatan atau bahkan potongan masa pada pelayan. Mendayakan rangsangan turbo mengurangkan prestasi satu utas pemproses disebabkan peningkatan dalam prestasi yang lain. Pada masa ini, maklumat tentang kekerapan pemproses semasa tidak dihantar ke mesin maya, dan ia percaya bahawa seseorang mencuri masanya (contohnya, ia meminta 2 GHz, tetapi menerima separuh daripada itu).

Secara umum, terdapat banyak sebab untuk herotan. Anda mungkin menemui sesuatu yang lain pada sistem tertentu. Adalah lebih baik untuk bermula dengan buku yang saya berikan pautan di atas, dan mendapatkan semula statistik daripada hipervisor menggunakan utiliti seperti perf, sysdig, systemtap, yang mana berpuluh-puluh.

5. Kesimpulan

  1. Beberapa jumlah mencuri mungkin berlaku disebabkan oleh paravirtualisasi, dan ia boleh dianggap biasa. Mereka menulis di Internet bahawa nilai ini boleh menjadi 5-10%. Bergantung pada aplikasi di dalam mesin maya dan pada beban yang diletakkan pada peranti fizikalnya. Di sini adalah penting untuk memberi perhatian kepada perasaan aplikasi di dalam mesin maya.
  2. Nisbah beban pada hypervisor dan mencuri di dalam mesin maya tidak selalunya saling berkaitan dengan jelas; kedua-dua anggaran mencuri boleh tersilap dalam situasi tertentu di bawah beban yang berbeza.
  3. Penjadual mempunyai sikap buruk terhadap proses yang banyak bertanya. Dia cuba memberi lebih sedikit kepada mereka yang meminta lebih. Mesin maya yang besar adalah jahat.
  4. Sedikit mencuri boleh menjadi norma walaupun tanpa paravirtualisasi (dengan mengambil kira beban di dalam mesin maya, ciri-ciri beban jiran, pengagihan beban merentas benang dan faktor lain).
  5. Jika anda ingin mengetahui mencuri dalam sistem tertentu, anda perlu meneroka pelbagai pilihan, mengumpul metrik, menganalisisnya dengan teliti dan memikirkan cara mengagihkan beban secara sama rata. Penyimpangan daripada mana-mana kes adalah mungkin, yang mesti disahkan secara eksperimen atau dilihat dalam debugger kernel.

Sumber: www.habr.com

Tambah komen