Investigasi: apa yang lebih tinggi dari prioritas utas di Windows?

Penyelidikan ini, seperti banyak penelitian lainnya, dimulai dengan fakta bahwa saya melakukan bisnis sendiri, bukan mencoba mencari masalah sendiri. Kali ini, yang saya lakukan hanyalah membuka tutup laptop dan mencoba masuk ke sistem.

Untuk beberapa kali pertama, ketika ini mengakibatkan penundaan dua puluh detik, saya mengabaikan masalahnya, berharap itu akan menyelesaikan sendiri. Beberapa kali berikutnya saya memikirkan penyelidikan, tetapi masalah kinerja yang muncul bahkan sebelum Anda masuk lebih sulit untuk diselesaikan, dan saya malas.

Ketika saya perhatikan bahwa saya menghindari menutup laptop karena saya takut keterlambatan ini terlalu sering, saya menyadari bahwa sudah waktunya untuk melakukan ini dengan serius.

Untungnya, saya baru-baru ini memperbaiki jejak buffer cincin UIforETWmembuatnya dapat diandalkan, jadi saya memulainya dan mulai menunggu acara penundaan berikutnya. Saya tidak perlu menunggu lama.

Saya perlu beberapa kali untuk mendapatkan jejak ETW dengan saya . Dan karena wilayah ini asing bagi saya, perlu beberapa waktu untuk mencari tahu apa yang terjadi. Saya masih belum sepenuhnya memahami masalahnya, tetapi 90% memahami alasan terjadinya. Saya berhasil belajar banyak, termasuk beberapa detail baru tentang Windows scheduler, dan saya juga menemukan solusi yang sangat efektif.

Jejak ideal yang akhirnya saya rekam saat memuat ke Microsoft Windows Performance Analyzer (WPA) terlihat seperti ini:


Peristiwa standar, jendela dalam fokus dan penggunaan CPU.

Tabel ini dan dua grafik berisi satu ton informasi. Tabel atas ( Acara Generik ) menunjukkan penekanan tombol yang direkam untuk UIforETW. Saya mencoba menekan tombol (kode kunci virtual 162) sekali per detik hingga bidang input kata sandi muncul. Karena 17 penekanan tombol ini dipilih, dalam grafik di bawah ini ditampilkan dengan garis biru vertikal untuk visualisasi yang disederhanakan dari waktu pelaksanaan peristiwa penting. Sumbu x mewakili waktu dalam detik.

Bilah horizontal pada grafik atas ( Jendela dalam Fokus ) menunjukkan proses mana yang memiliki fokus selama ini. Ada enam proses yang berbeda secara total. Periode Tracing off adalah waktu singkat di mana laptop ditutup.

Grafik bawah menunjukkan penggunaan CPU . Informasi diperoleh dari pemindahan data konteks, oleh karena itu harus sepenuhnya akurat dan lengkap. Dalam penelusuran ini, nilai 100% menunjukkan momen ketika semua delapan prosesor logis dari notebook delapan-inti empat-inti saya digunakan.

Setelah menerima data jejak, saya harus mencari tahu apa yang dilakukan laptop saya secara diam-diam ketika penutup ditutup dan sampai saat saya kembali ke sistem.

Badai sebelum jeda


Seperti yang bisa kita lihat, laptop di awal jejak laptop relatif sederhana, sebagaimana mestinya. Lalu aku menutup tutupnya. Ini tampaknya telah menyebabkan lonjakan aktivitas CPU dan perubahan fokus windows. Window in Focus berubah dari UIforETW ke Idle, lalu ke csrss, kembali ke Idle, ke LogonUI, dan kemudian kembali ke Idle. Siapa sangka?

Selama interval ini, laptop melakukan sekitar 17 detik pemrosesan CPU dari berbagai jenis. Sebagian darinya adalah pekerjaan yang harus dimatikan. Bagian - ini adalah program (termasuk alat Google internal) yang terdaftar di Penjadwal Tugas untuk pelaksanaan "Ketika pengguna mengunci workstation" - itu logis. Saya bahkan memperhatikan bahwa pekerjaan sedang dilakukan untuk membuat elemen UI untuk masuk ketika pengguna terus bekerja - Anda harus siap terlebih dahulu, bukan?

CPU 17 detik - waktu yang cukup lama untuk laptop untuk tidur. Bahkan di laptop saya dengan empat inti dan delapan utas, prosesnya memakan waktu lebih dari empat detik. Di laptop rumah saya, butuh lebih dari 13 detik waktu CPU untuk tertidur, dan hampir semuanya masuk ke kode Windows. Apakah layanan kebijakan diagnostik benar - benar perlu menjalankan beberapa pencarian SruDbTable sebelum laptop dapat beristirahat?

Saya pikir kerja yang berlebihan ini ketika akan tidur juga masalah, tapi ini bukan yang sangat masalah yang saya cari. Jadi saya memutuskan untuk memunggungi dia.

Dan baru kemudian saya menyadari bahwa pada saat inilah butiran kehancuran serangga saya dilemparkan ...

Tidur


Setelah memblokir laptop, tidak ada aktivitas CPU. Dalam pengujian khusus ini, laptop terkunci selama sekitar 16 detik.

Kebangkitan konvulsif


Aktivitas CPU pada transisi ke tidur tidak dapat dibandingkan dengan ketika mulai bangun. Selama waktu ini, laptop saya yang kelebihan beban memakan waktu sekitar 172 detik waktu CPU (!!!) selama 22,6 detik. Ini banyak pekerjaan.

Salah satu misteri dari proses ini adalah penurunan penggunaan CPU menjadi hampir nol sekitar satu detik setelah ledakan aktivitas awal. Periode waktu henti yang singkat ini tampaknya agak tidak normal, mengingat kekacauan di sekitarnya. Tapi saya pikir fitur ini tidak berhubungan dengan masalah, jadi saya tidak memperhatikannya.

Misteri lain adalah mengapa begitu banyakprogram menjadi hidup setelah jeda singkat ini. Lucu bahwa penyusup paling serius yang bertanggung jawab untuk 31,6 dari 172 detik CPU adalah Windows Performance Analyzer (WPA) - program yang saya gunakan untuk menganalisis jejak. Tiga salinan yang saya jalankan sedang bekerja keras untuk merender UI saya, meskipun belum terlihat.

Selain itu, pola gelap terjadi ketika mencoba menginisialisasi perangkat laptop. KeStallExecutionProcessor adalah loop menunggu, dan aneh melihat bahwa ini adalah fungsi yang paling dapat dieksekusi dari seluruh sistem. Apakah siklus tunggu kedua-aneh satu-satunya cara untuk memulai peralatan? Apakah benar-benar perlu menghabiskan waktu 700 ms CPU untuk menginisialisasi mouse dan keyboard ? Haruskah Microsoft dan Intel mengabaikan rekomendasi Microsoft padamaksimal 50 mikrodetik ?


Driver dari siklus menunggu. i8042prt.sys ditulis oleh Microsoft. Dua berikut ini dibuat oleh Intel.

Pada akhirnya, banyak program yang aktif berjalan selama ini . Sebagian besar dari mereka tampaknya menghadapi masalah yang sama dengan WPA - mereka putus asa untuk menggambar piksel pada layar tersembunyi, dan ini menyinggung bug Windows. Tetapi bahkan tanpa bug explorer.exe ini dan program lain secara aktif mencari sesuatu untuk dilakukan. Tetapi pada akhirnya, meskipun penggunaan CPU yang berlebihan ini merupakan bagian penting dari masalah, itu bukan masalah itu sendiri . Jadi sekali lagi saya berhenti memperhatikannya.

Fokus


Saat menganalisis jejak, penting untuk mengetahui kapan tindakan penting terjadi. Bukti utama adalah peristiwa input, karena saya berhenti mengklik kontrol setelah formulir input kata sandi muncul. Berikut adalah tiga penekanan tombol kontrol terakhir dalam bentuk perkiraan pada jendela di bagan Fokus :


Tampaknya peristiwa kritis mendapatkan fokus dari LockApp.exe, setelah itu fokus mendapat LogonUI.exe hampir secara instan. Agaknya, saya memasukkan kata sandi di LogonUI.exe (lebih mudah bahwa jejak tidak mencegat peristiwa keyboard), setelah itu fokus beralih ke explorer sebentar, dan kemudian ke UIforETW, dari mana saya mulai.

LogonUI.exe juga tidak bisa mendapatkan fokus sebelum LockApp.exe - pola ini berulang di semua jejak yang saya pelajari.

Jadi, setelah lebih dari seribu kata yang didedikasikan untuk memecahkan teka-teki ini, kami akhirnya memiliki pertanyaan yang jelas yang dapat kami selidiki: mengapa LockApp.exe mendapatkan fokus setelah keluar dari waktu henti, dibutuhkan dua puluh detik?

Kami punya pertanyaan? Bagus, mari kita jawab


Menggunakan data Penggunaan CPU (Tepat) yang diperoleh dari alih konten, saya segera menemukan bahwa dalam waktu dua puluh detik setelah bangun LockApp.exe menerima kurang dari satu milidetik waktu CPU, dan selama lebih dari 14 detik (dari 35,158 detik hingga 49,827 detik) tidak berfungsi umumnya:


LockApp tidak berfungsi sama sekali untuk waktu yang lama

Dokumentasi tentang arti kolom dalam tabel Penggunaan CPU (Precise) ada di sini .

Jika suatu proses atau utas belum berjalan selama beberapa waktu, dan Anda ingin mencari tahu mengapa, biasanya petunjuk penting dapat ditemukan dalam sakelar konteks pertama setelah jeda yang lama, yaitu beralih ke penelusuran selama 49,827 detik. Saya memesan ulang kolom untuk menampilkan lebih banyak data dari sakelar konteks ini:


LockApp disiapkan tetapi tidak dieksekusi. Aneh ...

Hitung, sama dengan 1 berarti kita melihat data untuk sakelar konteks tunggal.

Waktu Sejak Terakhir, sama dengan 38,2 juta mikrodetik, berarti utas ini tidak akan dijalankan dalam 38,2 detik. Ini sendiri tidak baik atau buruk. Aliran yang menganggur menghemat energi, dan pada akhirnya laptop itu dalam mimpi selama beberapa waktu.

Switch-In Time hanya memberi tahu kita kapan tepatnya thread tersebut cocok dengan CPU - ketika konteksnya beralih ke thread tersebut.

Dan sekarang kita pergi ke kolom Ready. Dia memberi tahu kami berapa lama utas itu siap untuk dieksekusi, tetapi tidak dieksekusi. Dengan kata lain, utas ini sedang menunggu sesuatu (kunci, pegangan) dan ini adalah sesuatudibebaskan atau diinisiasi, tetapi utas masih tidak berjalan selama 19,493 detik.

Untuk lebih memahami kolom Siap (kami) , Anda dapat melihat pada kolom Waktu Siap . Dia memberi tahu kita ketika sungai disiapkan. Kita melihat bahwa selama 30,333 detik penelusuran, utas ini disiapkan untuk eksekusi, tetapi tidak dieksekusi hingga 49,827 detik. Ini sepertinya penting.

Susunan kolom ini sebaliknya menunjukkan kepada kita saklar konteks yang sama:


Stack Thread Baru dan Stack Thread Ready

Jadi, thread ini (yang diharapkan oleh Stack Thread Baru NtWaitForWorkViaWorkerFactory untuk ditampilkan) diperintahkan untuk bangun (proses sistem yang memanggil KeSetEvent) tidak lama setelah saya membuka tutup notebook selama 30,333 detik penelusuran. Tapi itu tidak dimulai pada saat itu (yang akan menjadi "baik"), tetapi setelah 19.494 detik, dan ini buruk.

Biasanya, ketika melakukan analisis harapan seperti itu, saya menghabiskan banyak waktu untuk mencari tahu mengapa aliran menunggu dan apa yang menyebabkannya tidak siap. Tetapi ini adalah pertama kalinya saya melakukan analisis harapan, di mana itu tidak penting, dan pertanyaannya adalah mengapa utas yang sudah jadi ini tidak dieksekusi.

Kasing ...


Kebanyakan orang tidak menghabiskan begitu banyak waktu mempelajari jejak ETW, jadi diperlukan penjelasan di sini. Ini sangat aneh. Jika utas sudah siap, maka biasanya mulai seketika, atau setelah beberapa milidetik. Kesiapan streaming, seperti namanya , berarti streaming siap untuk dieksekusi dan hampir tidak ada yang dapat mengganggu itu. Tapi mari kita cari tahu apa yang bisa mencegah eksekusi utas jadi.

Prioritas utas


Pada awalnya saya menyarankan bahwa ini adalah kasus sederhana dari "lapar" CPU. Lusinan proses membutuhkan waktu CPU, dan karena itu, LockApp tidak mendapatkan yang benar sampai beban berkurang. Namun, teori ini tidak sesuai dengan gejalanya, karena proses LockApp dapat memakan waktu sekitar 18 detik bahkan tanpa waktu CPU.

Teori kelaparan CPU baik karena dapat diverifikasi. Saya berhasil meningkatkan prioritas proses LockApp menggunakan Task Manager (selama salah satu periode singkat ketika itu tidak ditangguhkan oleh sistem UWP), oleh karena itu, dalam penelusuran akhir yang saya gunakan untuk posting ini, LockApp dieksekusi dengan prioritas tinggi. Utas Windows biasa berjalan dengan prioritas sekitar 8-10. Prioritas tertinggi yang dapat dijalankan utas Windows reguler (non-waktu nyata) adalah 15. Jejak ETW saya menunjukkan bahwa LockApp selalu bekerja dengan prioritas 13 atau lebih tinggi.

Berikut adalah timeline CPU untuk kritis 19,494 detik, dikelompokkan dan diwarnai berdasarkan prioritas utas ( New In Pri, prioritas saat ini yang ditugaskan ke utas). Kami melihat bahwa utas dengan prioritas 4, 8, 9, dan 10 menghabiskan sebagian besar waktu CPU, terutama di akhir:


Menggunakan CPU berdasarkan Prioritas

Berikut adalah gambar lain dengan utas tersembunyi dengan prioritas 0-12. Setiap kali grafik turun di bawah 12,5% (yang berarti satu prosesor logis dari waktu CPU delapan-thread notebook saya), LockApp harus diluncurkan, dan itu menjadi sangat sulit dipercaya bahwa prioritas mencegahnya dieksekusi begitu sering ketika banyak utas dengan prioritas yang lebih rendah atau sama dapatkan banyak waktu.


Prioritas penggunaan CPU, utas prioritas tinggi saja

Hilangkan inversi prioritas


Ada spekulasi bahwa algoritma inversi prioritas Windows sangat kondusif untuk utas lainnya sehingga LockApp.exe diblokir. Tetapi karena grafik yang ditunjukkan di atas menunjukkan bahwa prioritas yang sebenarnya digunakan dalam keputusan perencanaan, asumsi ini (selalu tidak meyakinkan) harus ditinggalkan.

Stack core unloading


Ketika saya berbicara tentang teka-teki ini di Twitter, salah satu komentator menyarankan agar tumpukan inti thread diturunkan . Saya tidak terbiasa dengan situasi ini, tetapi setelah penjelasan John Werth (dia mengerti di bidangnya) saya mematikan swapping tumpukan kernel dan menyalakan kembali komputer. Tidak ada yang berubah. Bahkan, saya tidak berpikir bahwa ini akan membantu, mengingat saya memiliki memori 32 GB, dan masalah terjadi berulang kali dan sering; tapi lebih baik memastikan ini.

Jeda proses


Karena LockApp adalah aplikasi UWP modern, ini tunduk pada pembatasan yang serupa dengan yang ada pada aplikasi ponsel cerdas. Antara lain, ini berarti bahwa itu dapat ditangguhkan ketika tidak di latar depan, dan kemudian "mencairkan" ketika kembali ke latar depan. James Forshaw mengusulkan rekaman ETW Microsoft-Windows-Kernel-Process untuk mendapatkan data tentang ini.

Acara dirancang untuk menyebabkan kebingungan maksimal. Nama tugas Process Freeze digunakan untuk "pencairan" dan "pembekuan", dan versi dari win: Stop event berarti bahwa prosesnya dimulai (telah berhenti membeku), dan versi dari win: Startberarti proses berhenti (mulai membeku). Semua ini sangat logis, tetapi sangat membingungkan. Jika nama acara dibagi menjadi Freeze dan Thaw, maka akan ada lebih sedikit kebingungan.

Tidak ada dokumentasi untuk acara ini, tetapi berkat analisisnya, saya memutuskan bahwa acara ini selalu dibuat oleh Tugas Latar Belakang / Layanan Infrastruktur Pialang . Nama dan ID proses dari proses yang sesuai ditunjukkan di bidang FrozenProcessID.


ProcessFreeze Events (juga digunakan untuk pencairan es) Sangat

menarik untuk menyelidiki penyedia ini - ia memiliki banyak peristiwa yang menjanjikan - tetapi pada akhirnya ternyata LockApp tidak berhenti atau mencairkan es selama penelusuran. Namun, penyedia ini sepertinya cukup berguna, jadi saya memodifikasi UIforETW sehingga versi yang akan datang selalu mencatatnya.

Kami sudah mengesampingkan semuanya


Bagi saya, tidak ada satu pun teori yang diuraikan di atas yang sangat mungkin, dan sekarang kita semua telah menyisihkannya. Saya mulai mencari bantuan, dan meminta saya untuk memberi saya ide dari seorang teman dari Microsoft. Dan pada saat itu saya menemukan bahwa aliran prioritas 0-31 yang sangat terkenal di Windows sebenarnya hanya lima bit prioritas rendah dari sistem prioritas penuh .

Penggunaan posisi resmi


Ternyata ketidaktahuan saya adalah kesalahan saya sendiri. Jika saya membaca dengan seksama semua 108 halaman bagian Threads dari Windows Internal, Edisi 7, Bagian 1 , saya akan mengerti apa yang terjadi. Jika Anda ingin melompat maju, maka topik ini diungkapkan pada halaman 287 hingga 295 .

Bidang super-prioritas yang tidak saya ketahui ini disebut Peringkat . Itu muncul di WPA sebagai kolom tersembunyi default (untuk menemukannya, Anda harus membuka View Editor) yang disebut NewThreadRank . Saat merencanakan utas, Peringkat Utas memiliki prioritas di atas prioritas. Hampir semua aliran memiliki Peringkat 0, dan aliran dengan Peringkat 0 selalu memiliki prioritas lebih tinggi daripada aliran dengan Peringkat 2. Dengan menyertakan kolomNewThreadRank dan melihat sisi kiri meja, kita dapat langsung melihat masalahnya:


Peringkat lebih penting daripada prioritas

. Streaming LockApp.exe memiliki Peringkat 2, yang berarti bahwa meskipun prioritas 14, mereka memiliki prioritas terendah dalam sistem.

Penjelasan yang hampir lengkap


Karena ternyata utas LockApp.exe memiliki Peringkat 2, mereka hanya dapat dieksekusi ketika tidak ada utas dengan Peringkat 0 “ingin” dijalankan. Karena banyak aplikasi (untuk alasan yang tidak diketahui) secara aktif membuat layar mereka yang tidak terlihat, mereka berjuang untuk setiap remah waktu CPU, tidak meninggalkan apa pun untuk peringkat yang lebih tinggi. Setelah LockApp.exe menerima sebagian kecil dari waktu CPU, dengan cepat pindah ke Peringkat 0 (dan beban CPU turun), setelah itu proses login dilakukan dengan cara biasa.

Setelah mempelajari informasi ini, saya mulai mempelajari bagaimana peringkat LockApp berubah dari waktu ke waktu. Dalam beberapa detik terakhir sebelum tidur, LockApp tiba-tiba pindah dari peringkat 0 ke 2. Peringkat tersebut dirancang untuk mencegah CPU mengambil terlalu banyak waktu, seperti ketika Foto Windows terlalu tertarik pada pemrosesan latar belakang yang tidak diinginkan dan melakukan transisi dari peringkat 2 hingga 19:


Microsoft.Foto turun peringkat

Dari dokumentasi Anda dapat memahami bahwa tujuan utama peringkat aliran adalah pembagian waktu CPU yang adil antar sesi pada mesin sehingga proses satu pengguna tidak membahayakan orang lain. Kedua opsi ini untuk menggunakan peringkat memperjelas bahwa peringkat aliran hanya akan meningkat jika menggunakan banyak waktu CPU, dan ketika laptop pergi tidur, LockApp.exe hanya menggunakan 79,3 ms dari waktu CPU, dan sisa sistem - 17 dari waktu CPU . Namun demikian, OS untuk beberapa alasan memutuskan untuk menurunkan versi LockApp ke 2 dalam proses tidur.

OS mengubah peringkat aliran hanya jika itu milik "kelompok perencanaan" ( KSCHEDULING_GROUP), dan kebanyakan utas di instalasi Windows biasa bukan anggota. Akibatnya, sebagian besar utas tidak tunduk pada perubahan peringkat, sehingga mereka dapat menghabiskan waktu CPU seperti yang mereka inginkan.

Teka-teki yang tersisa


Sayangnya, masih belum jelas mengapa LockApp.exe turun ke peringkat 2 sebelum menyalakan sleep.I akan menganggap bahwa LockApp berada di grup perencanaan dan mungkin salah satu algoritma berperilaku salah. Tetapi saya tidak dapat menemukan API untuk menyelidiki ini, dan waktu sudah hampir habis. Jika Anda mengetahui detailnya, maka tuliskan komentar di artikel asli. Prinsip menggunakan peringkat sebagai komponen terpenting dalam keputusan perencanaan seharusnya, menurut saya, mau tidak mau hancur jika sebagian besar proses dalam sistem tidak terlibat di dalamnya - utas dalam kelompok perencanaan selalu menghadapi risiko dibiarkan tanpa sumber daya yang diperlukan. Perencanaan Alokasi Sumber Daya Dinamis ( DFSS ) pasti akan gagal jika kebanyakan utas tidak terlibat.

Juga, saya tidak tahu mengapa begitu banyak aplikasi tetap aktif setelah tidur. Ini biasanya dijelaskan oleh fakta bahwa “banyak penghitung waktu berakhir ketika laptop dalam mode tidur selama beberapa jam,” tetapi penjelasan ini tidak cocok jika laptop tersebut hanya dalam mimpi selama beberapa detik, dan perilaku rendering WPA menunjukkan bahwa sesuatu terjadi dalam sistem jendela sesuatu yang salah. Tambahkan ke aplikasi perilaku buruk dan driver siklus menunggu, dan semuanya ditumpuk dari waktu ke waktu oleh CPU.

Fakta bahwa badai CPU mereda dan LockApp mulai pada saat yang sama mengarah ke penjelasan yang jelas: LockApp hanya dapat bekerja ketika permintaan CPU turun. Tetapi ada penjelasan yang sama meyakinkannya: begitu LockApp mendapatkan kemampuan untuk menjalankan (atau, mungkin, LogonUI mendapatkannya), permintaan CPU turun. Kedua penjelasan bekerja, tetapi saya pikir yang terakhir lebih masuk akal, karena kalau tidak kita tidak bisa menjelaskan mengapa rendering WPA yang tampaknya tak berkesudahan tiba-tiba berhenti.

Solusi untuk masalah tersebut


Segera setelah saya menyadari bahwa LockApp.exe adalah aplikasi terpisah yang memiliki masalah dengan peluncuran, dan meningkatkan prioritasnya tidak membantu, saya menonaktifkannya. File DisableLockScreen.reg membantu saya dengan ini:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization]
“NoLockScreen”=dword:00000001

Dengan mematikan layar kunci, laptop bangun segera setelah membuka penutup. Saya tidak melihat pengereman atau badai CPU, dan sekarang hanya perlu satu langkah lebih sedikit untuk masuk.

The Posting Pertama twitter saya diposting ketika saya pertama kali mengalami masalah berisi kerangka waktu untuk penyelidikan yang mungkin berguna untuk seseorang. Selain itu, banyak orang pintar dari twitter datang ke pos tersebut, terima kasih kepada mereka.

Ketika saya kembali ke artikel tersebut, saya menemukan bahwa setelah menyalakan kembali layar kunci, masalahnya hilang. Sebuah reboot sederhana tidak memperbaikinya - pada bulan Februari saya reboot berkali-kali, tetapi kami mungkin tidak tahu mengapa itu hilang.

Diskusi



All Articles