Jarayon ustuvorligi: nice, renice va CPU vaqtini adolatli taqsimlash
Odatiy serverda istalgan lahzada ishga tayyor jarayonlar CPU yadrolaridan ancha ko'p bo'ladi: veb-server, ma’lumotlar bazasi, zaxira nusxa skripti va monitoring agenti bir vaqtda CPU vaqtini xohlaydi, lekin har bir yadro bir vaqtda aynan bitta ko'rsatmalar oqimini bajara oladi. Kernelning rejalashtiruvchisi (scheduler) soniyasiga ko'p marta qaysi ishga tayyor jarayon yadroni keyingi bo'lib va qancha muddatga olishini hal qiladi. Ko'pincha standart rejalashtirish siyosati yetarli va ko'rinmaydi. U muhim bo'ladigan paytlar aynan shu yerda ko'rib chiqiladi: fondagi paketli ish interaktiv xizmatni CPU’siz qoldirmasligi kerak bo'lganda yoki muhim jarayonni kamroq muhim ish ortida kutib qolishdan himoya qilish kerak bo'lganda.
Bu maqolada nice qiymatlari rejalashtiruvchining qarorlariga qanday ta’sir qilishini, ularni nice va renice bilan qanday o'rnatish va o'zgartirishni ko'rib chiqamiz. Shuningdek, faqat nice har qanday ustuvorlik muammosini hal qilmagani uchun real vaqt (real-time) rejalashtirish siyosatlari va I/O ustuvorligi (ionice) shu manzaraga qanday sig'ishini ham ko'ramiz.
Nice qiymatlari: kafolat emas, og'dirish
Linux’ning oddiy jarayonlar uchun standart rejalashtiruvchisi (hozir ishlatilayotgan ko'pchilik kernellarda Completely Fair Scheduler, CFS) har bir jarayonga bir xil, belgilangan vaqt bo'lagini bermaydi. Buning o'rniga har bir jarayonning -20 (eng yuqori rejalashtirish ustuvorligi) dan 19 (eng past) gacha bo'lgan nice qiymati bor va rejalashtiruvchi undan bitta yadro uchun raqobatlashayotgan boshqa jarayonlarga nisbatan jarayon qancha CPU vaqti olishga haqli ekanini hisoblashda vazn sifatida foydalanadi. Standart, o'zgartirilmagan jarayon 0 nice qiymati bilan ishlaydi.
Nom ataylab ma’noli tanlangan: jarayonning nice qiymatini oshirish uni boshqalarga nisbatan "muloyimroq" (nicer) qiladi — u boshqa jarayonlar ko'proq ishlashi uchun ixtiyoriy ravishda kichikroq CPU ulushiga rozi bo'ladi.
NI — siz o'rnatgan nice qiymati; PRI esa nice qiymati ta’sir qiladigan, kernel hisoblagan haqiqiy rejalashtirish ustuvorligi (bu yerda yuqoriroq PRI ertaroq rejalashtirilishini bildiradi). PRI ning aniq raqamli qoidasi NI nikidan farq qiladi va bu ko'p chalkashlikka sabab bo'ladi; biror narsani sozlayotganda har doim PRI emas, NI bo'yicha fikr yuriting.
Warning
Nice qiymati — kafolatlangan ulush ham, qat’iy chegara ham emas, balki nisbiy og'dirish. Agar ustuvorligi pasaytirilgan jarayon (NI 19) aks holda bo'sh turgan yadrodagi yagona ishga tayyor jarayon bo'lsa, u baribir o'sha yadroning 100% ini oladi. Nice qiymatlari faqat bir nechta jarayon aynan bir vaqtda bitta CPU uchun haqiqatan raqobatlashganda ahamiyatli. Yuqori nice qiymatini o'rnatish bo'sh tizimda jarayonning CPU sarfini cheklamaydi.
Jarayonni tanlangan ustuvorlik bilan ishga tushirish: nice
-n 15 backup-script.sh ni 15 nice qiymati bilan ishga tushiradi — bu bitta yadro uchun raqobatlashayotgan har qanday muhimroq narsaga CPU vaqtini osonlikcha bo'shatib beradigan past ustuvorlikli fon ishi. Aniq daraja ko'rsatilmasa, nice shell’ning joriy nice qiymatiga standart siljishni (odatda 10) qo'llaydi.
Ustuvorlikni standartdan (0) yuqori ko'tarish yuqori huquq talab qiladi, chunki imtiyozsiz jarayonga boshqa hamma narsadan ustuvorlikni erkin egallashga ruxsat berish tizimning qolgan qismini CPU’siz qoldirishning oson yo'li bo'lardi:
sudo siz manfiy nice qiymatini o'rnatishga uringan oddiy foydalanuvchi shell va tizim sozlamalariga qarab xato yoki jimgina cheklangan qiymat oladi. So'ralgan qiymat kuchga kirgan deb o'ylamasdan, keyin har doim ps -o ni bilan tekshiring.
Ishlab turgan jarayonning ustuvorligini o'zgartirish: renice
nice faqat jarayon ishga tushayotgan paytda qo'llanadi. Allaqachon ishlab turgan jarayonni sozlash uchun renice dan foydalaning:
-p to'g'ridan-to'g'ri PID ni nishonga oladi. renice muayyan foydalanuvchiga tegishli barcha jarayonlarni qayta nishonga olish uchun -u <user> ni va jarayonlar guruhi uchun -g <group> ni ham qabul qiladi. Bu har bir PID ni alohida qidirish o'rniga butun paketli ishning bola jarayonlari ustuvorligini bitta buyruq bilan pasaytirish uchun foydali.
nice dagidek, nice qiymatini joriy darajasidan pastga yoki umuman 0 dan pastga tushirish (jarayonni ko'proq afzal qilish) buni qilish huquqini talab qiladi. Imtiyozsiz foydalanuvchi o'z jarayonining nice qiymatini faqat oshira oladi (uni kamroq afzal qila oladi), hech qachon pasaytira olmaydi. Bu foydalanuvchiga administrator ataylab cheklagan jarayonning ustuvorligini qaytarib olishga yo'l qo'ymaydi.
Real vaqt rejalashtirish: nice yetarli bo'lmaganda
Nice qiymatlari ustuvorlikni faqat oddiy, "imkon qadar" (best-effort) rejalashtirish sinfi ichida sozlaydi. Haqiqatan boshqa hamma narsani siqib chiqarishi shart bo'lgan jarayon uchun — past kechikishli audio pipeline, ba’zi sanoat boshqaruv dasturlari — Linux real vaqt rejalashtirish siyosatlarini (SCHED_FIFO, SCHED_RR) taklif qiladi. Ular nice qiymati boshqaradigan barcha oddiy jarayonlardan yuqori turadigan butunlay alohida, yuqoriroq ustuvorlikli sinfda joylashgan:
chrt -f real vaqt ustuvorligi 50 bilan SCHED_FIFO ni o'rnatadi (bir xil real vaqt ustuvorligidagi jarayonlar orasida birinchi kelgan birinchi xizmat qilinadi va u bloklanmaguncha yoki joy bo'shatmaguncha ishlaydi). Real vaqt ustuvorliklari 1–99 oralig'ida bo'ladi, 99 eng yuqorisi — bu oddiy nice qiymatlaridan alohida, belgilangan raqamli oraliq.
Danger
Real vaqt rejalashtirish nice dan tubdan farq qiladigan vosita va noto'g'ri ishlatilsa, uning ta’sir doirasi ancha katta. Hech qachon ixtiyoriy bloklanmaydigan yoki joy bo'shatmaydigan SCHED_FIFO jarayoni tizimdagi har bir oddiy jarayonni, jumladan oddiy ustuvorlikda ishlaydigan muhim kernel xizmat thread’larini ham CPU’siz qoldirishi va mashinani faqat apparatni qayta yoqish bilan tiklanadigan darajada javob bermaydigan holatga keltirishi mumkin. Umumiy maqsadli xizmatga avval bir martalik mashinada sinab ko'rmasdan real vaqt siyosatini o'rnatmang va muayyan ish yuki cheksiz qattiq siklda aylanmasdan, vaqti-vaqti bilan sched_yield() ni chaqirishi yoki bloklanishini doim tasdiqlang.
CPU ustuvorligi I/O ustuvorligi emas: ionice
Qulay nice qiymatiga ega jarayon ham sekin disk I/O ni kutayotgan bo'lsa, baribir jiddiy kechikishi mumkin, chunki nice qiymatlari kernel blok I/O so'rovlariga qaysi tartibda xizmat ko'rsatishini emas, faqat CPU rejalashtirishini boshqaradi. ionice ostidagi I/O rejalashtiruvchisi uni qo'llab-quvvatlasa, aynan shu alohida o'qni hal qiladi (odatda cfq yoki bfq bilan; NVMe qurilmalarida keng tarqalgan standart none/mq-deadline ostida kamroq samarali):
-c 3 idle I/O sinfini o'rnatadi — bu jarayonning I/O so'rovlariga faqat boshqa hech bir jarayonga disk umuman kerak bo'lmaganda xizmat ko'rsatiladi. Bu oldingi plandagi diskka bog'liq ishga hech qanday ta’sir qilmasligi kerak bo'lgan fondagi zaxira nusxa yoki indekslash ishi uchun ideal. -c 2 (best-effort, standart) undan keyin 0–7 ustuvorlik darajasini qabul qiladi; -c 1 (real vaqt) imtiyozli, kechikishga o'ta sezgir I/O uchun ajratilgan va keng qo'llansa, real vaqt CPU rejalashtirishidagi kabi resurssiz qoldirish xavfiga ega.
Ikkalasini bitta qatorda birlashtirish — eng past CPU ustuvorligi va idle I/O sinfi — mashinada ishlayotgan boshqa hamma narsa uchun amalda ko'rinmas bo'lishi kerak bo'lgan zaxira nusxa ishi uchun standart andoza.
Real vaziyat: tungi zaxira nusxa veb-serverni sekinlashtirmoqda
Muammo. Har kecha soat 02:00 da tar asosidagi zaxira nusxa ishi ishga tushadi va monitoring shu oraliqda veb-serverdagi so'rovlar kechikishi keskin oshayotganini ko'rsatadi. Zaxira nusxaning o'zini kechiktirmasdan yoki buzmasdan uning ta’sirini kamaytirish kerak.
Biror narsani o'zgartirishdan oldin sabab haqiqatan zaxira nusxa ekanini tasdiqlang:
Zaxira nusxa oralig'ida top ning %Cpu(s) qatorini tekshiring (Jarayonlarni kuzatish maqolasida ko'rilganidek). Agar zaxira nusxa faolligi bilan birga wa (I/O kutish) ham oshgan bo'lsa, to'siq disk raqobati va uni faqat nice hal qilmaydi; bu yerda kerakli vosita — ionice.
Zaxira nusxa jarayonlar guruhiga CPU va I/O ustuvorligini pasaytirishni birga qo'llang:
backup_pid=$(pgrep -f 'full-backup.sh' | head -1)
renice -n 19 -p "$backup_pid"
ionice -c 3 -p "$backup_pid"
Tekshiring:
Uzoq muddatli yaxshiroq yechim. Har kecha jarayon ishga tushgandan keyin uning ustuvorligini qo'lda o'zgartirish o'rniga, zaxira nusxaning o'z ishga tushirish buyrug'ini — uning cron yozuvi yoki systemd unit’ini — boshidanoq to'g'ri ustuvorlik bilan ishga tushadigan qilib tahrirlang:
Xulosa. Agar bu o'zgarishdan keyin zaxira nusxa oralig'idagi veb-server kechikishi yaxshilansa, asl muammo zaxira nusxa veb-server bilan teng sharoitda raqobatlashganidan kelib chiqqan CPU va/yoki I/O raqobati bo'lgan. Uning ustuvorligini manbaning o'zida (keyinchalik qo'lda bajariladigan renice da emas, ishga tushirish buyrug'ida) pasaytirish kelgusi har bir ishga tushirishda xuddi shu shikoyat takrorlanishining oldini oladi. Agar kechikish yaxshilanmasa, to'siq boshqa joyda — tarmoqda, ma’lumotlar bazasi so'rovi vaqtida yoki ilova darajasidagi raqobatda — va ustuvorlikni sozlash aynan shu alomat uchun noto'g'ri vosita bo'lgan.
Keng tarqalgan xatolar
nice bo'sh tizimda CPU sarfini cheklaydi deb kutish
Ustuvorligi pasaytirilgan jarayon, agar o'sha paytda unga hech kim raqib bo'lmasa, baribir yadroning 100% ini oladi. Nice qiymatlari faqat raqobat paytida ahamiyatli; ular CPU kvota mexanizmi emas (haqiqiy kvota vositasi — production mavzularida boshqa joyda ko'rib chiqiladigan cgroups CPU chegaralari).
NI va PRI ni adashtirish
PRI ning raqamli qoidasi (va uning aniq oralig'i) NI ning -20 dan 19 gacha shkalasi bilan bir xil emas. Ustuvorlikni har doim NI orqali o'rnating va u haqida NI bo'yicha fikr yuriting, PRI ga esa faqat kernel ichida hisoblanadigan, hosilaviy ko'rsatkich sifatida qarang.
Real vaqt rejalashtirishni kuchliroq nice sifatida ishlatish
SCHED_FIFO/SCHED_RR "o'ta manfiy nice qiymatlari" emas — ular butun oddiy rejalashtirish sinfini, jumladan -20 nice qiymatiga ega jarayon ham vaqtni bo'lishishi kerak bo'lgan jarayonlarni siqib chiqaradi. Real vaqt rejalashtirishga faqat haqiqatan qat’iy kechikish kafolatlarini talab qiladigan ish yuklari uchun va faqat bir martalik tizimda sinab ko'rgandan keyin murojaat qiling.
CPU ustuvorligini pasaytirib, I/O ni unutish
Qulay nice qiymati berilgan paketli ish faqat disk raqobati orqali ham interaktiv ishni to'xtatib qo'yishi mumkin. Sezilarli fayl I/O bajaradigan har qanday fon ishi uchun renice ni ionice bilan birga qo'llang.
Ishning faqat ota jarayoni ustuvorligini o'zgartirish
Shell skriptining o'z ustuvorligini o'zgartirish u keyinchalik ishga tushiradigan har bir bola jarayonga avtomatik o'tmaydi — agar skriptning o'zi kerakli nice qiymati bilan ishga tushirilmagan bo'lsa yoki butun jarayonlar guruhiga renice -p/-g qo'llanmagan bo'lsa. Har bir tegishli bola jarayon haqiqatan ko'zlangan ustuvorlikni meros qilib olganini ps --forest bilan tekshiring.
Mashqlar
- Ikkita CPU’ni band qiladigan siklni (
yes > /dev/null &ni ikki marta) mos ravishda0va19nice qiymatlari bilan ishga tushiring, so'ngtopdagi ikkalasining%CPUustunini kuzating. Kuzatgan nisbatingizni belgilangan foiz taqsimoti bilan emas, rejalashtirish vazni orqali tushuntiring. - O'zingizning joriy shell sessiyangizga nisbatan
renice -n 10 -u <your-username>ni qo'llang vaps -o niyordamida nima o'zgargani va nima o'zgarmaganini, shuningdek keyin uni yana0dan pastga tushirish negasudosiz muvaffaqiyatsiz bo'lishini tushuntiring. - Taxminiy
nightly-export.shskriptini keyinchalik sozlash o'rniga ishga tushgan paytidanoq eng past CPU ustuvorligi va idle I/O sinfi bilan ishga tushiradigan bitta buyruqni yozing. - Hech narsani ishga tushirmasdan, ichida hech qanday bloklovchi chaqiruv bo'lmagan cheksiz siklli yomon yozilgan xizmatga
chrt -f -p 99ni o'rnatish nega xuddi shu xizmatgarenice -n -20ni o'rnatishdan xavfliroq ekanini tushuntiring.
Mashqni bajardim deyish uchun: "jarayonni nice qilish uning CPU sarfini cheklaydi" degan har qanday da’vo noto'g'ri va javoblaringizda bo'lmasligi kerak — to'g'ri ifoda har doim mutlaq chegara emas, raqobat ostidagi nisbiy ustuvorlik.
Manbalar
- Linux man-pages:
nice(1),renice(1): https://man7.org/linux/man-pages/man1/nice.1.html - Linux man-pages:
sched(7): https://man7.org/linux/man-pages/man7/sched.7.html - Linux man-pages:
chrt(1): https://man7.org/linux/man-pages/man1/chrt.1.html - Linux man-pages:
ionice(1): https://man7.org/linux/man-pages/man1/ionice.1.html - Linux kernel hujjatlari: CFS scheduler design: https://www.kernel.org/doc/html/latest/scheduler/sched-design-CFS.html
- Linux kernel hujjatlari: real-time scheduling: https://www.kernel.org/doc/html/latest/scheduler/sched-rt-group.html
- Linux man-pages:
setpriority(2),getpriority(2): https://man7.org/linux/man-pages/man2/setpriority.2.html