LIFO Cache (Last In First Out Cache) — kesh maksimal hajmga yetganda oxirgi qo'shilgan elementni siqib chiqaradigan keshlash algoritmi. Murojaat namunasini hisobga oladigan LRU dan farqli o'laroq, LIFO faqat qo'shish tartibiga tayanadi: yangi element avvalgi yangi elementni siqib chiqaradi. Android Developers (2026) ma'lumotiga ko'ra, LIFO Cache faqat navigatsiya steklari va operatsiyalarni bekor qilish buferi kabi tor stsenariylarda samarali.
Asosiy fikrlar
LIFO Cache (Last In First Out Cache) — stek asosida amalga oshirilgan cheklangan hajmdagi keshdir. To'liq keshga yangi element qo'shilganda eng yangi (yuqori) element o'chiriladi va yangi element uning o'rnini egallaydi. «Last In First Out» nomi keshga eng oxirgi kirgan element eng birinchi o'chirilishini anglatadi.
Bunday siyosat LRU va FIFO dan tubdan farq qiladi. LRU eng dolzarb ma'lumotlarni (oxirgi murojaat vaqtiga ko'ra) saqlashga harakat qilganda, FIFO ma'lumotlarning «yoshi» ni saqlaydi, LIFO esa ataylab yangi ma'lumotlarni qurbon qiladi. Bu keshlash uchun mantiqsiz tuyulishi mumkin, ammo ma'lum stsenariylarda LIFO optimal yechim bo'lib chiqadi.
Klassik LIFO Cache amali massiv yoki bog'langan ro'yxat asosidagi stekdan foydalanadi. Massiv ixcham saqlash va kesh mahalliyligini ta'minlaydi, lekin maxSize uchun oldindan xotira ajratishni talab qiladi. Bog'langan ro'yxat moslashuvchanroq, lekin har bir element ko'rsatkichlar uchun qo'shimcha xotira talab qiladi (har bir element uchun 8–16 bayt).
push(value) operatsiyasi elementni stekning tepasiga qo'shadi. Hajmi maxSize ga yetgan bo'lsa, qo'shishdan oldin tepa o'chiriladi. pop() operatsiyasi yuqori elementni o'chiradi va qaytaradi — «oxirgi amalni bekor qilish» stsenariylari uchun foydali. peek() operatsiyasi yuqori elementni o'chirmasdan qaytaradi — stekni o'zgartirmasdan oxirgi saqlangan holatni ko'rish uchun.
LIFO Cache ning ishlash printsipi juda sodda: barcha operatsiyalar strukturaning bir uchida — stekning tepasida bajariladi. Yangi element qo'shilganda u tepaga joylashtiriladi. Agar stek to'la bo'lsa, yuqori element itarib chiqariladi (o'chiriladi) va yangi element uning o'rnini egallaydi. Siqib chiqarish har doim faqat bitta elementga — tepaga ta'sir qiladi, shuning uchun algoritm qidirish yoki saralashni talab qilmaydi.
Bu xususiyat LIFO Cache ni barcha siqib chiqarish siyosatlari orasida eng tezkor qiladi: barcha operatsiyalar hech qanday qo'shimcha ma'lumot tuzilmalarisiz O(1) vaqtida bajariladi. Qidirish uchun xesh-jadval, qayta tartiblash uchun ikki tomonlama bog'langan ro'yxat kerak emas — stekning tepasiga oddiy ko'rsatkich yetarli. Xotira minimal sarflanadi: faqat elementlarning o'zini saqlash uchun.
Biroq soddalikning salbiy tomoni ham bor: LIFO Cache ma'lumotlarga murojaat chastotasi yoki oxirgi murojaat vaqtini hisobga olmaydi. Agar dastur avval A, B, C ma'lumotlarini, so'ngra yana A ni so'rasa — to'lib ketganda C (oxirgi qo'shilgan) o'chiriladi, hatto A endi dolzarb bo'lmasa ham. Umumiy keshlash stsenariylari uchun bu LIFO ni eng yomon tanlovga aylantiradi, chunki yangi ma'lumotlar ko'pincha eng qimmatlidir.
Massiv asosidagi LIFO Cache uchun hajm yaratilish vaqtida belgilanadi va dinamik o'zgarmaydi. Agar stek to'la bo'lsa va push sodir bo'lsa — yuqori element ustiga yoziladi. Bog'langan ro'yxatdagi amalda har bir element uchun xotira kerak bo'lganda ajratiladi, lekin limitga yetilganda eski tugun ajratiladi va axlat yig'uvchi tomonidan to'planishi mumkin. Mobil ilovalarda LIFO Cache uchun massivdan foydalanish tavsiya etiladi, chunki u GC ga qo'shimcha yuk yaratmaydi.
Siqib chiqarish strategiyasini tanlash keshlash samaradorligiga bevosita ta'sir qiladi. LIFO, LRU va FIFO bitta savolga turli yondashuvlarni ifodalaydi: to'lib ketganda qaysi elementni o'chirish kerak? Har bir yondashuv o'z vazifalar sinfi uchun optimaldir.
| Parametr | LIFO | FIFO | LRU |
|---|---|---|---|
| Siqib chiqarish mezoni | Oxirgi qo'shilgan | Birinchi qo'shilgan | Eng kam ishlatilgan |
| Tuzilma | Stek | Navbat | HashMap + Doubly Linked List |
| Hit-ratio | Past (10–30%) | O'rtacha (40–60%) | Yuqori (60–95%) |
| Amalga oshirish murakkabligi | Minimal | Past | O'rtacha |
| Xotira sarfi | Minimal | Past | O'rtacha (qo'shimcha ko'rsatkichlar) |
LRU odatda eng yaxshi hit-ratio beradi, lekin ko'proq xotira va murakkabroq amal talab qiladi. FIFO — samaradorlik va hit-ratio o'rtasida murosadir, oqim ma'lumotlari uchun foydali. LIFO — eng sodda, ammo past hit-ratio bilan: uni faqat «oxirgi kelgan — birinchi chiqadi» semantikasi biznes mantiqiga mos kelganda qo'llash kerak (navigatsiya, operatsiyalarni bekor qilish).
Umumiy keshlash uchun cheklangan yaroqliligiga qaramasdan, LIFO Cache ma'lumotlarni qayta ishlash tartibi qabul qilish tartibiga teskari bo'lgan aniq stsenariylarda qo'llaniladi. Asosiy holatlarni ko'rib chiqaylik.
Mobil ilovalarda navigatsiya stekidan foydalaniladi: yangi ekran ochilganda u stekning tepasiga joylashtiriladi, «Orqaga» tugmasi bosilganda olib tashlanadi. Agar stek chuqurligi cheklansa (masalan, maksimal 10 ekran), LIFO Cache limitdan oshganda avtomatik ravishda eng oxirgi ekranni o'chiradi. Bu avval ochilgan ekranlarni yo'qotmasdan navigatsiya stekining xotira sarfini boshqarish imkonini beradi.
Amallarni bekor qilish mexanizmi (Undo) — LIFO ning klassik namunasidir. Foydalanuvchining har bir amali stekda saqlanadi. Undo chaqirilganda oxirgi amal bekor qilinadi va Redo stekiga ko'chiriladi. LIFO Cache orqali stek hajmlarini cheklash limitdan oshganda eng eski amallar (stekning tubida) qolishini va eng yangilari tashlab yuborilishini ta'minlaydi — bu mantiqiy, chunki foydalanuvchi odatda so'nggi amallarni bekor qiladi va eskilari endi dolzarb emas.
Qaytish (backtracking) bilan rekursiv hisoblashlarda oraliq qadamlarning natijalari LIFO tartibida saqlanadi. Bufer to'lib ketganda oxirgi natija tashlab yuboriladi — bu maqbul, chunki algoritm kerak bo'lganda uni qayta hisoblashi mumkin. Bu yondashuv parserlarda, kompilyatorlarda va chuqurlik cheklovi bo'lgan grafikni aylanib o'tish algoritmlarida qo'llaniladi.
Kotlin da LIFO Cache ni o'lchami qat'iy belgilangan massiv yordamida amalga oshirishni ko'rib chiqaylik. Massiv mobil qurilmalar uchun eng yaxshi samaradorlik va minimal xotira sarfini ta'minlaydi.
class LifoCache<V>(
private val maxSize: Int
) {
private val array = arrayOfNulls<V>(maxSize)
private var top = -1
fun push(value: V) {
if (top == maxSize - 1) {
top-- // to'la bo'lganda eng eskisini tashla
}
array[++top] = value
}
fun pop(): V? {
if (top == -1) return null
val result = array[top]
array[top--] = null
return result
}
fun peek(): V? {
return array[top]
}
}
top indeksi stekning tepasiga ishora qiladi. push top ni oshiradi va qiymatni yozadi; agar massiv to'la bo'lsa (top == maxSize - 1), yozishdan oldin top kamaytiriladi — stekning tepasi ustiga yoziladi, bu LIFO siqib chiqarishni amalga oshiradi. pop metodi elementni qaytaradi va top ni kamaytiradi, peek esa stekni o'zgartirmasdan yuqori elementni o'qiydi.
Jetpack Compose da navigatsiya chuqurligini cheklash uchun LIFO Cache dan foydalanishni ko'rib chiqaylik. Yangi ekran ochilganda u stekga qo'shiladi va limitdan oshganda eng oxirgi ekran siqib chiqariladi.
class NavigationStack(maxDepth: Int = 10) {
private val cache = LifoCache<Screen>(maxDepth)
fun navigateTo(screen: Screen) {
cache.push(screen)
}
fun goBack(): Screen? {
return cache.pop()
}
fun currentScreen(): Screen? {
return cache.peek()
}
}
Bu misolda NavigationStack ekranlar tarixini saqlash uchun LIFO Cache dan foydalanadi. navigateTo chaqirilganda ekran stekga qo'shiladi, goBack da esa oxirgisi o'chiriladi. Agar foydalanuvchi limit 10 bo'lgan holda 11 ekran ochsa, eng oxirgisi (11-chi) avvalgisini (10-chi) siqib chiqaradi — birinchi ekran stekda qoladi, bu orqaga qaytishda foydalanuvchi kutganiga mos keladi. Bu strategiya navigatsiya uchun LRU dan samaraliroq: allaqachon ochilgan ekranlarni («bosh sahifa», «profil») o'chirish kutilmagan xatti-harakatga olib kelardi.
Tez-tez beriladigan savollar
LIFO qayta kerak bo'lish ehtimoli yuqori bo'lgan yangi ma'lumotlarni o'chiradi — bu murojaat mahalliyligi printsipiga ziddir. Aksariyat ilovalar yaqinda so'ralgan ma'lumotlar eng dolzarb bo'lgan namunani ko'rsatadi, shuning uchun LRU yoki LFU umumiy stsenariylarda ancha yaxshi hit-ratio beradi.
LIFO Cache cheklangan sig'imli stekdir. Stek LIFO printsipi bo'yicha ishlaydi: oxirgi qo'shilgan element tepada joylashgan. To'lib ketganda stekning tepasidagi element (oxirgisi) o'chiriladi va yangi element uning o'rnini egallaydi. Bitta top indeksli massiv yetarli — hech qanday qo'shimcha tuzilmalar talab qilinmaydi.
LIFO yangi ma'lumotlar eskilardan kamroq qiymatga ega bo'lgan stsenariylarda samaraliroq: navigatsiya steki (oxirgi ekran birinchi o'chirilishi kerak), Undo/Redo (oxirgi amal birinchi bekor qilinadi), rekursiv hisoblash buferlari (backtracking). Bu hollarda LIFO nafaqat sodda, balki semantik jihatdan LRU dan to'g'riroqdir.
Ha, gibrid yondashuvlar mavjud. Masalan, LIFO + FIFO: operativ qayta ishlash uchun LIFO (buyruqlar steki) va uzoq muddatli saqlash uchun FIFO (natijalar navbati). ARC (Adaptive Replacement Cache) kabi adaptiv algoritmlar kirish namunasiga qarab LRU va LFO o'rtasida dinamik ravishda o'tadi, lekin LIFO gibrid komponenti sifatida kam uchraydi.
N havola/qiymat massivi to'liq N × element_hajmi bayt va massiv obyektining o'zi uchun kichik qo'shimcha yuk (JVM da 24–40 bayt) egallaydi. LRU dan farqli o'laroq, qo'shimcha prev/next ko'rsatkichlari (Doubly Linked List da har bir element uchun 16 bayt) talab qilinmaydi. Cheklangan xotiraga ega mobil qurilmalar uchun massiv asosidagi LIFO eng tejamkor amaldir.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.