Kechasi ishga tushirilgan import skripti ertalab yarim yo'lda to'xtab qolgan, logda esa faqat bitta so'z yozilgan: Killed. Yoki onlayn do'konning katta hisobot sahifasi ochilmasdan 500 xato beradi. Bu holatlarning umumiy sababi ko'pincha bir xil: jarayon o'ziga ruxsat etilgan operativ xotiradan ko'proq so'ragan va tizim uni majburan to'xtatgan. Bunday holat ingliz tilida OOM, ya'ni "out of memory" deb ataladi. Ushbu maqolada OOM qanday yuzaga kelishini, uni boshqa xatolardan qanday ajratishni va kodni qanday qilib xotirani tejab ishlaydigan qilishni ko'rib chiqamiz.
Ikki xil xotira chegarasi
Hostingda xotira bilan bog'liq ikkita alohida chegara bor va ularni chalkashtirish ko'p vaqtni yo'qotishga olib keladi. Birinchisi - PHP'ning o'z sozlamasi bo'lgan memory_limit. U bitta PHP skript qancha xotira ishlatishi mumkinligini belgilaydi. Skript bu chegaradan oshsa, PHP o'zi ishni to'xtatadi va logga aniq xabar yozadi:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 20480 bytes) in /var/www/USER/data/www/example.uz/report.php on line 42
Bu xabarda qaysi fayl va qaysi qatorda xotira tugagani ko'rsatilgan, shuning uchun sababni topish nisbatan oson. 134217728 bayt 128 megabaytga teng, ya'ni skript shu chegaraga yetgan.
Ikkinchi chegara - butun akkauntingiz uchun ajratilgan RAM. U PHP, Python, Node.js va boshqa barcha jarayonlaringiz xotirasini birgalikda hisoblaydi. Agar jami xotira shu chegaradan oshsa, operatsion tizim jarayonlardan birini, odatda eng ko'p xotira olganini, ogohlantirishsiz to'xtatadi. Bu holda dastur o'zi xato yozishga ulgurmaydi: terminalda Killed so'zi chiqadi, veb-sahifa esa 500 yoki 503 xato bilan yakunlanadi. Aynan shu holat OOM kill deb ataladi.
OOM belgilarini qanday tanish mumkin
Ba'zi belgilar OOM'ga aniq ishora qiladi. Python yoki Node.js skript ishlayotgan joyida izsiz to'xtab qoladi va chiqish kodi 137 bo'ladi. Bu kod jarayon tashqaridan SIGKILL signali bilan o'ldirilganini bildiradi. Uzoq ishlaydigan bot yoki ilova vaqti-vaqti bilan o'z-o'zidan qayta ishga tushadi. Sayt odatda yaxshi ishlaydi, lekin katta eksport, rasm yuklash yoki og'ir hisobot paytida xato beradi. Hosting panelidagi resurs grafigida esa xotira chizig'i aynan shu daqiqalarda yuqori chegaraga tegib turadi.
Quyidagi buyruqlar qaysi jarayon qancha xotira olayotganini aniqlashga yordam beradi:
# Jarayonlaringiz xotira bo'yicha saralangan (RSS, kilobaytda)
ps -u "$USER" -o pid,rss,etime,cmd --sort=-rss | head
# Skript ishlaganda eng ko'p qancha xotira olganini o'lchash
/usr/bin/time -v python3 import_orders.py 2>&1 | grep "Maximum resident"
# Oxirgi buyruq "Killed" bilan tugagan bo'lsa, chiqish kodi 137 bo'ladi
echo $?
ps buyrug'i jarayonlaringizni xotira hajmi bo'yicha saralaydi. /usr/bin/time -v esa skript ishi davomida eng yuqori xotira iste'molini ko'rsatadi, bu raqamni tarifingizdagi RAM chegarasi bilan solishtirish mumkin.
Xotira nega tugaydi: odatiy sabablar
Butun ma'lumotni birdaniga yuklash
Eng ko'p uchraydigan xato - katta faylni yoki bazadagi butun jadvalni bir marta xotiraga o'qish. Yuz ming qatorli Excel fayl yoki buyurtmalar jadvali xotirada asl hajmidan bir necha barobar ko'p joy egallaydi, chunki har bir qiymat dastur ichida alohida obyektga aylanadi.
Katta rasmlarni qayta ishlash
Telefon kamerasidan olingan rasm diskda bir necha megabayt bo'lsa ham, o'lchamini o'zgartirish uchun ochilganda u siqilmagan holda xotiraga yoziladi va o'nlab megabayt joy oladi. Bir vaqtda bir nechta shunday rasm yuklansa, xotira tez tugaydi.
Juda ko'p ishchi jarayonlar
Python ilovalarini Gunicorn yoki shunga o'xshash serverlar bilan ishga tushirganda har bir ishchi (worker) ilovaning to'liq nusxasini xotirada saqlaydi. To'rtta ishchi to'rt barobar xotira degani. Umumiy hosting yoki kichik VPS uchun ishchilar soni ko'pincha ortiqcha belgilanadi.
Xotira oqishi
Ba'zan dastur ishlatib bo'lgan xotirani bo'shatmaydi: masalan, har bir so'rovda global ro'yxatga yangi element qo'shiladi va u hech qachon tozalanmaydi. Bunday ilova bir necha soat yaxshi ishlaydi, keyin esa sekin-asta xotirani to'ldirib, OOM bilan to'xtaydi.
Misol: Buxorodagi restoran boti
Buxorodagi restoran buyurtmalar uchun Python'da yozilgan Telegram bot ishlatardi. Har kuni kechqurun administrator Excel fayldan oylik hisobotni botga yuklar, bot esa uni tahlil qilib bazaga yozardi. Fayl kattalashgan sari bot har safar shu paytda to'xtab qola boshladi, logda esa faqat Killed qolardi. Tekshiruv shuni ko'rsatdiki, fayl to'liq xotiraga ochilib, keyin barcha qatorlar avval ro'yxatga yig'ilib, so'ngra bazaga yozilayotgan edi. Kod qatorma-qator ishlaydigan qilib o'zgartirildi:
from openpyxl import load_workbook
# read_only=True faylni to'liq xotiraga yuklamaydi
wb = load_workbook("buyurtmalar.xlsx", read_only=True)
ws = wb.active
for row in ws.iter_rows(min_row=2, values_only=True):
save_order(row) # har bir qatorni darhol bazaga yozish
wb.close()
Shundan keyin skriptning eng yuqori xotira iste'moli keskin kamaydi va bot to'xtashni bas qildi. Muammo kuchliroq tarif bilan emas, ikki qator kodni o'zgartirish bilan hal bo'ldi.
Xotirani tejash usullari
PHP'da katta eksport yoki hisobotlarni bo'laklab bajarish eng samarali yo'l. Butun jadvalni bir so'rovda olish o'rniga uni qismlarga bo'lib ishlash xotira iste'molini barqaror ushlab turadi:
// Hammasini bir marta olish o'rniga 500 tadan bo'lib ishlash
$offset = 0;
do {
$rows = $db->query("SELECT id, name, total FROM orders ORDER BY id LIMIT 500 OFFSET $offset")->fetchAll();
foreach ($rows as $r) { fputcsv($out, $r); }
$offset += 500;
} while (count($rows) === 500);
Python veb-ilovalari uchun ishchilar sonini real ehtiyojga moslang va xotira oqishi bo'lsa, ishchilarni ma'lum miqdordagi so'rovdan keyin avtomatik yangilab turing:
gunicorn app:app --workers 2 --max-requests 500 --max-requests-jitter 50
Bu sozlama har bir ishchini taxminan 500 so'rovdan keyin qayta yaratadi va oqib ketgan xotira bo'shaydi. Bu vaqtinchalik yechim ekanini unutmang: oqishning asl sababini topish baribir kerak. Rasmlar uchun esa yuklash paytida maksimal o'lchamni cheklang va ularni navbat bilan, bittadan qayta ishlang.
memory_limit qiymatini oshirish ham ba'zan to'g'ri qadam, masalan WordPress administrator panelida og'ir plagin ishlayotgan bo'lsa. Lekin bu faqat PHP chegarasini ko'taradi, akkauntning umumiy RAM chegarasini emas. Agar akkaunt chegarasi tugayotgan bo'lsa, memory_limit'ni oshirish OOM kill'ni tezlashtirishi ham mumkin.
Qachon ko'proq RAM kerak
Agar kod optimallashtirilgan, ishchilar soni to'g'ri va oqish yo'q bo'lsa-yu, ilova baribir chegarada ishlasa, demak unga haqiqatan ko'proq xotira kerak. Doimiy ishlaydigan botlar, Node.js yoki Python ilovalar uchun ko'pincha VPS qulayroq, chunki u yerda xotira faqat sizniki va jarayonlarni o'zingiz boshqarasiz. sayt.uz kabinetidan hosting tarifini o'zgartirish yoki VPS buyurtma qilish mumkin, resurs grafiklari bo'yicha savollar bo'lsa, sayt.uz texnik yordamiga tiket yozing.