[Android] Hello๐Ÿ‘‹, Out Of Memory

Sehee Jeongยท2021๋…„ 5์›” 28์ผ
4
post-thumbnail
post-custom-banner

Hello๐Ÿ‘‹, Out Of Memory


๐Ÿƒโ€โ™‚๏ธ Android Memory

์ด๋ฏธ์ง€ ๋กœ๋” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ๋งŽ์€ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๊ณ ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€๋ฅผ ์ด๋ฏธ์ง€๋ทฐ์— ๋กœ๋“œํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ์œผ๋กœ OOM์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค. ์š”์ฆ˜ ๋‚˜์˜ค๋Š” ์Šค๋งˆํŠธํฐ์€ ๊ต‰์žฅํžˆ ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฐ€์ง€๊ณ  ํƒœ์–ด๋‚˜๋Š”๋ฐ ์™œ ์ด์ •๋„๋„ ๋ชป ๋ฒ„ํ‹ฐ์ง€(?) ๋ผ๋Š” ์ƒ๊ฐ์„ ํ•œ๋‹ค๋ฉด, ์•ˆ๋“œ๋กœ์ด๋“œ๋Š” ์•ฑ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ •ํ•ด์ ธ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Android์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ์€ ์šด์˜์ฒด์ œ ๋ฒ„์ „์— ๋”ฐ๋ผ ๋‘๊ฐ€์ง€๋กœ ๋‚˜๋‰˜๊ฒŒ ๋œ๋‹ค.

  • Dalvik heap ์˜์—ญ : java ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ
  • External ์˜์—ญ : native heap์˜ ์ผ์ข…์œผ๋กœ ๋„ค์ดํ‹ฐ๋ธŒ์˜ ๋น„ํŠธ๋งต ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ
    Dalvik heap ์˜์—ญ์™€ External ์˜์—ญ์˜ Dalvik heap footprint + External Limit์„ ํ•ฉ์ณ ํ”„๋กœ์„ธ์Šค๋‹น ๋ฉ”๋ชจ๋ฆฌ ํ•œ๊ณ„๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด OOM์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

๐Ÿƒโ€โ™‚๏ธ Footprint

java์˜ footprint๋Š” ํ•œ ๋ฒˆ ์ฆ๊ฐ€ํ•˜๋ฉด ํฌ๊ธฐ๊ฐ€ ๋‹ค์‹œ ๊ฐ์†Œ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, footprint๊ฐ€ ๊ณผ๋„ํ•˜๊ฒŒ ์ปค์ง€์ง€ ์•Š๊ฒŒ๋” ์ž˜ ๊ด€๋ฆฌํ•ด์•ผํ•œ๋‹ค.

Dalvik VM์€ ์ฒ˜์Œ์— ๋™์ž‘์— ํ•„์š”ํ•œ ๋งŒํผ๋งŒ ํ”„๋กœ์„ธ์Šค์— Heap์„ ํ• ๋‹นํ•˜๊ฒŒ ๋˜๊ณ , ํ”„๋กœ์„ธ์Šค์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ณด๋‹ค ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•„์š”ํ•˜๊ฒŒ๋  ๋•Œ๋งˆ๋‹ค Dalvit Footfrint๋„ ์ฆ๊ฐ€ํ•˜๊ฒŒ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์ฆ๊ฐ€๋œ Footfrint๋Š” ๊ฒฐ์ฝ” ๊ฐ์†Œํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— java ๊ฐ์ฒด๊ฐ€ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์˜ ์—ฌ์œ ๊ฐ€ ์žˆ์–ด๋„, External heap์˜ ํฌ๊ธฐ๊ฐ€ ์ฆ๊ฐ€๋˜๋ฉด OOM์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ฌธ์ œ๋„ Honeycomb ์ดํ›„๋ถ€ํ„ฐ๋Š” Dalvik heap ๊ณผ External ์˜์—ญ์ด ํ•ฉ์ณ์กŒ๊ธฐ ๋•Œ๋ฌธ์—, ๊ณ ๋ คํ•  ํ•„์š”๊ฐ€ ์—†์–ด์กŒ๋‹ค.

External ์˜์—ญ์„ ์‚ฌ์šฉํ•˜๋Š” Honeycomb ๋ฏธ๋งŒ ๋ฒ„์ „์—์„œ๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ณ ์žˆ๋Š” ํ™”๋ฉด์—์„œ ํ™”๋ฉด์„ ์ „ํ™˜ํ•˜๋Š” ํ–‰๋™์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ๋„ OOM์ด ๋ฐœ์ƒํ•˜๋ฉด์„œ ์•ฑ์ด ์ค‘์ง€๋  ๊ฒƒ์ด๋‹ค. ํ™”๋ฉด์„ ์ „ํ™˜ํ•˜๋ฉด ์ด์ „ ์•กํ‹ฐ๋น„ํ‹ฐ ์ธ์Šคํ„ด์Šค์— ์žˆ๋˜ ์ด๋ฏธ์ง€๋ทฐ๋‚˜ ํ• ๋‹น๋˜์—ˆ๋˜ ๋น„ํŠธ๋งต์ด ํ•จ๊ป˜ ์†Œ๋ฉธ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํšŒ์ˆ˜๋˜๊ณ  ์ƒˆ๋กœ์šด ์•กํ‹ฐ๋น„ํ‹ฐ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ• ํ…๋ฐ, ์ด ๊ณผ์ •์—์„œ ์ด์ „ ์•กํ‹ฐ๋น„ํ‹ฐ ์ธ์Šคํ„ด์Šค์˜ ๋น„ํŠธ๋งต ๊ฐ์ฒด๊ฐ€ ํšŒ์ˆ˜๋˜์ง€ ์•Š์•„ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋น„ํŠธ๋งต ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์—†๋Š”๋ฐ๋„ ์™œ ํšŒ์ˆ˜๊ฐ€ ๋  ์ˆ˜ ์—†์„๊นŒ?๐Ÿค” Honeycomb ๋ฏธ๋งŒ ๋ฒ„์ „์—์„œ๋Š” Java ๋น„ํŠธ๋งต ๊ฐ์ฒด๋Š” ์‹ค์ œ ๋น„ํŠธ๋งต ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ณณ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ์ผ ๋ฟ์ด๊ณ  ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” External ์˜์—ญ์ธ Native Heap ์˜์—ญ์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. Java ๋น„ํŠธ๋งต ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๊ฐ€ ์—†์„ ๋•Œ GC์— ์˜ํ•ด ํšŒ์ˆ˜๋˜์ง€๋งŒ Native Heap ์˜์—ญ์€ GC ์ˆ˜ํ–‰์˜์—ญ ๋ฐ–์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋ฉธ ์‹œ์ ์ด ๋‹ค๋ฅด๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ์  ๋•Œ๋ฌธ์—, Honeycomb ์ดํ›„ ๋ฒ„์ „์—์„œ๋Š” External ์˜์—ญ์ด ์—†์–ด์ง€๋ฉด์„œ Dalvik heap ์˜์—ญ์— ๋น„ํŠธ๋งต ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์˜ฌ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๊ณ  GC๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

๋‹ค์‹œ ๋Œ์•„์™€, ๋งŒ์•ฝ ๊ณ ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•  ๋•Œ OOM์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ BitmapFactory ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด ๋‹ค์šด์ƒ˜ํ”Œ๋ง, ๋””์ฝ”๋”ฉ ๋ฐฉ์‹์„ ์„ ํƒํ•ด ์ ์ ˆํ•˜๊ฒŒ ๋ทฐ์— ๋กœ๋“œํ•˜๋ฉด ๋œ๋‹ค. ํ•˜์ง€๋งŒ ๋งŽ์€ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด์„œ OOM์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ์ด๋ฏธ์ง€ ์บ์‹ฑ์„ ์ด์šฉํ•ด๋ณด๋Š” ๊ฒƒ์ด ์–ด๋–จ๊นŒ?

๐Ÿƒโ€โ™‚๏ธ Bitmap Caching

์ด๋ฏธ์ง€๊ฐ€ ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง€๊ณ  ๋‹ค์‹œ ๊ตฌ์„ฑํ•  ๋•Œ ์ด๋ฏธ์ง€๋ฅผ ๋งค๋ฒˆ ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์€ ์„ฑ๋Šฅ์ƒ์œผ๋กœ๋‚˜ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ์ข‹์ง€ ์•Š๋‹ค. ์ด๋Ÿด ๋•Œ ๋ฉ”๋ชจ๋ฆฌ์™€ ๋””์Šคํฌ ์บ์‹œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์–ด๋””์—์„ ๊ฐ€ ์ €์žฅ๋˜์–ด์žˆ๋˜ ๋น„ํŠธ๋งต์„ ๋‹ค์‹œ ๊ฐ€์ ธ์˜จ๋‹ค๋ฉด ๋‹ค์‹œ ๋กœ๋“œํ•˜๋Š” ์‹œ๊ฐ„๋„ ๋‹จ์ถ•์‹œํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์„ฑ๋Šฅ ๊ฐœ์„ ๋„ ๊ฐ€๋Šฅํ•  ๊ฒƒ์ด๋‹ค. ์ด ๋•Œ ์บ์‹ฑ์„ ์œ„ํ•ด Memory Cache์™€ Disk Cache ์‚ฌ์šฉ์„ ์ถ”์ฒœํ•˜๋Š”๋ฐ ๋‘๊ฐ€์ง€๊ฐ€ ์–ด๋–ค ์ฐจ์ด์ ์ด ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž.

1. Memory Cache

Memory Cache๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์— ์กด์žฌํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ๋น„ํŠธ๋งต์„ ์บ์‹ฑํ•˜๊ณ , ํ•„์š”ํ•  ๋•Œ ๋น ๋ฅด๊ฒŒ ์ ‘๊ทผ๊ฐ€๋Šฅํ•˜๋‹ค. ํ•˜์ง€๋งŒ Memory Cache๋„ ๊ณง ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์šฉ๋Ÿ‰์„ ํ‚ค์šฐ๋Š” ์ฃผ๋ฒ”์ด ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์€ ์บ์‹ฑ์„ ์š”๊ตฌํ•˜๋Š” ๋น„ํŠธ๋งต์˜ ๊ฒฝ์šฐ์—๋Š” Disk Cache์— ๋„ฃ๋Š” ๊ฒƒ์ด ๋” ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค.

2. Disk Cache

Memory Cache์— ๋„ฃ๊ธฐ์—” ๋งŽ์€ ์บ์‹œ๋ฅผ ์š”๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ, ํ˜น์€ ์•ฑ์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ ์ „ํ™˜๋˜์–ด๋„ ์ ์žฌํ•œ ์บ์‹œ๊ฐ€ ์‚ญ์ œ๋˜์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ž€๋‹ค๋ฉด Disk Cache๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ํ•˜์ง€๋งŒ Disk๋กœ๋ถ€ํ„ฐ ์บ์‹ฑ๋œ ๋น„ํŠธ๋งต์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ๋Š” Memory์—์„œ ๋กœ๋“œํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์˜ค๋žœ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค.

๐Ÿƒโ€โ™‚๏ธ BitmapPool

Memory Cache์˜ ์˜ˆ์‹œ๋ฅผ ์œ„ํ•ด ์†Œ๊ฐœํ•  ๊ฒƒ์€ BitmapPool์ด๋‹ค. BitmapPool์˜ ์›๋ฆฌ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” Bitmap์„ ๋ฆฌ์ŠคํŠธ์— ๋„ฃ์–ด๋†“๊ณ , ์ถ”ํ›„์— ๋™์ผํ•œ ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•  ๋•Œ ๋‹ค์‹œ ๋ฉ”๋ชจ๋ฆฌ์— ์ ์žฌํ•˜์ง€ ์•Š๊ณ  pool์— ์žˆ๋Š” ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์™€ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋ณดํ†ต BitmapPool์„ ์ด์šฉํ•ด ์žฌ์‚ฌ์šฉ Pool์„ ๋งŒ๋“ค๊ฒŒ ๋  ๋•Œ, LRU ์บ์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๊ตฌํ˜„๋œ LinkedList (lruBItmapList)์™€ Byte Size ์ˆœ์œผ๋กœ ์ •๋ ฌ๋œ LinkedList(bitmapList)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋œ๋‹ค. ์ด ๋‘˜์€ ๋“ค์–ด์žˆ๋Š” ๋น„ํŠธ๋งต์˜ ์ˆœ์„œ๋งŒ ๋‹ค๋ฅผ ๋ฟ, ๊ฐ™์€ ๋น„ํŠธ๋งต์ด ๋‹ด๊ธฐ๊ฒŒ๋œ๋‹ค.

     private val lruBitmapList = LinkedList<Bitmap>()
     private val bitmapList = LinkedList<Bitmap>()

LRU ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•ด ์˜ค๋žซ๋™์•ˆ ์ฐธ์กฐ๋˜์ง€์•Š์€ ๋น„ํŠธ๋งต ๊ฐ์ฒด๋Š” ๋งจ ๋’ค๋กœ ๋ฐ€๋ฆฌ๊ฒŒ๋˜๊ณ , ๋งจ ๋’ค์—์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ํšŒ์ˆ˜ํ•˜๋ฉด์„œ BitmapPool์„ ์œ ์ง€์‹œํ‚ค๋Š” ๊ฒƒ์ด๋‹ค. LRU ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ฒ˜์Œ BitmapPool์ด ๊ฐ€๋“ ์ฐฐ ๋•Œ๊นŒ์ง€๋Š” ๋ฌธ์ œ์—†์ด ๋™์ž‘ํ•˜์ง€๋งŒ, ๋น„ํŠธ๋งต์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ์‹œ์ ๋ถ€ํ„ฐ๋Š” ํŠน์ • ๋น„ํŠธ๋งต๋งŒ ์žฌ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์•ฑ์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ค„์–ด๋“ค์ง€ ์•Š๊ฒŒ๋œ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค. :)

๋Œ€ํ‘œ์ ์ธ ์ด๋ฏธ์ง€ ๋กœ๋” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Glide์—์„œ ๊ตฌํ˜„ํ•œ LruBitmapPool Class ๋‚ด๋ถ€๋ฅผ ๋ณด๋ฉฐ, LruBitmapList์™€ bitmapList๊ฐ€ ์–ด๋–ป๊ฒŒ ์“ฐ์ด๊ณ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด์ž.

public class LruBitmapPool implements BitmapPool {
  private static final String TAG = "LruBitmapPool";
  private static final Bitmap.Config DEFAULT_CONFIG = Bitmap.Config.ARGB_8888;

  private final LruPoolStrategy strategy;
  private final Set<Bitmap.Config> allowedConfigs;
  private final BitmapTracker tracker;
  
  // Pool์— ๋“ค์–ด์˜ฌ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ํฌ๊ธฐ
  private long maxSize;
  // ํ˜„์žฌ pool์— ๋“ค์–ด๊ฐ„ bitmap byte ํฌ๊ธฐ
  private long currentSize;

Glide๋‚ด LruBitmapPool Class ์—์„œ๋Š” strategy(LruPoolStrategy)๊ฐ€ ๊ณง LRU ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋œ ๋ฆฌ์ŠคํŠธ์ด๋ฉฐ, tracker(BitmapTracker)๊ฐ€ Bitmap size ์ˆœ์œผ๋กœ ์ •๋ ฌ๋œ ๋ฆฌ์ŠคํŠธ์ด๋‹ค.

 @Override
  public synchronized void put(Bitmap bitmap) {
    if (bitmap == null) {
      throw new NullPointerException("Bitmap must not be null");
    }
    // isRecycled: ์žฌํ™œ์šฉ๋œ bitmap์ธ์ง€ ์—ฌ๋ถ€
    if (bitmap.isRecycled()) {
      throw new IllegalStateException("Cannot pool recycled bitmap");
    }
    // isMutable: canvas๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” bitmap ์ธ์ง€ ์—ฌ๋ถ€.
    if (!bitmap.isMutable()
        || strategy.getSize(bitmap) > maxSize
        || !allowedConfigs.contains(bitmap.getConfig())) {
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(
            TAG,
            "Reject bitmap from pool"
                + ", bitmap: "
                + strategy.logBitmap(bitmap)
                + ", is mutable: "
                + bitmap.isMutable()
                + ", is allowed config: "
                + allowedConfigs.contains(bitmap.getConfig()));
      }
      bitmap.recycle();
      return;
    }
    // pool์— ๋„ฃ์œผ๋ ค๋Š” bitmap์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ์–ป์–ด์˜จ๋‹ค.
    final int size = strategy.getSize(bitmap);
    strategy.put(bitmap);
    tracker.add(bitmap);

    puts++;
    currentSize += size;

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      Log.v(TAG, "Put bitmap in pool=" + strategy.logBitmap(bitmap));
    }
    dump();

    evict();
  }

Bitmap์„ Pool์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ์กฐ๊ฑด์„ ์ถฉ์กฑ์‹œํ‚จ๋‹ค๋ฉด, strategy & tracker์— bitmap์ด ๋“ค์–ด๊ฐ€๊ฒŒ๋œ๋‹ค.

fyi. Lru ๊ธฐ๋ฐ˜์ธ strategy ๋Š” ์ตœ๊ทผ์— ๋“ค์–ด์˜จ bitmap์ผ์ˆ˜๋ก ๋ฆฌ์ŠคํŠธ์˜ ๋งจ ์•ž์œผ๋กœ ๋ฐฐ์น˜์‹œ์ผœ์•ผํ•˜๋Š”๋ฐ, ๊ทธ ๋กœ์ง์ด LruPoolStrategy ๊ตฌํ˜„์ฒด ๋‚ด๋ถ€์— ์กด์žฌํ•˜๊ฒŒ ๋œ๋‹ค.


// Pool์˜ ์ตœ๋Œ€ ์‚ฌ์šฉ๋Ÿ‰์„ ๋„˜๊ธฐ๋ฉด ํฌ๊ธฐ๋ฅผ ์ค„์—ฌ์ค€๋‹ค.
  private synchronized void trimToSize(long size) {
    while (currentSize > size) {
    //LRU List์—์„œ ์‚ญ์ œํ•œ๋‹ค.
      final Bitmap removed = strategy.removeLast();
      if (removed == null) {
        if (Log.isLoggable(TAG, Log.WARN)) {
          Log.w(TAG, "Size mismatch, resetting");
          dumpUnchecked();
        }
        currentSize = 0;
        return;
      }
      // BitmapList์—์„œ ์‚ญ์ œํ•œ๋‹ค. 
      tracker.remove(removed);
      currentSize -= strategy.getSize(removed);
      evictions++;
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Evicting bitmap=" + strategy.logBitmap(removed));
      }
      dump();
      removed.recycle();
    }
  }

trimToSize()๋ฅผ ์ด์šฉํ•˜๋ฉด pool์ด ์ตœ๋Œ€์‚ฌ์šฉ๋Ÿ‰์„ ๋„˜์–ด์„  ๊ฒฝ์šฐ ์ฐธ์กฐ๋ฅผ ๊ฐ€์žฅ ์ ๊ฒŒํ•˜๊ณ  ์žˆ๋Š” lastIndex ๋ถ€ํ„ฐ ๊ฐ์ฒด๋ฅผ ์ง€์›Œ๊ฐ€๋ฉฐ ํฌ๊ธฐ๋ฅผ ์ค„์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค.

  @Override
  @Nullable
  public Bitmap get(int width, int height, Bitmap.Config config) {
    final int size = Util.getBitmapByteSize(width, height, config);
    Key key = keyPool.get(size);

    Integer possibleSize = sortedSizes.ceilingKey(size);
    if (possibleSize != null && possibleSize != size && possibleSize <= size * MAX_SIZE_MULTIPLE) {
      keyPool.offer(key);
      key = keyPool.get(possibleSize);
    }

    final Bitmap result = groupedMap.get(key);
    // ๋น„ํŠธ๋งต์„ ์ฐพ์€ ๊ฒฝ์šฐ, pool์—์„œ ์ œ๊ฑฐํ•œ๋‹ค.
    if (result != null) {
      result.reconfigure(width, height, config);
      decrementBitmapOfSize(possibleSize);
    }

    return result;
  }

์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด pool์—์„œ ํ•„์š”ํ•œ ๋น„ํŠธ๋งต์„ ๊ฐ€์ ธ์˜จ๋‹ค.

๐Ÿƒโ€โ™‚๏ธ End

Glide์˜ BitmapPool ๋‚ด๋ถ€๋งŒ ์ž ๊น ๋ณด์•˜๋Š”๋ฐ๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ๋งŽ์€ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ด๊ฒจ์ ธ์žˆ๋‹ค. ์ด๋ฏธ์ง€๋ทฐ์— ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”๋กœ ๋กœ๋“œํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด, Out of memory, Slow Loading, Bitmap Caching, Memory Cache, Gabarge collector ์ด์Šˆ ๋“ฑ๋“ฑ... ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ณ ๋ คํ•ด์•ผํ•˜๋Š” ์š”์†Œ๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ๊ธฐ์— ์ด๋ฅผ third party library์—๊ฒŒ ์œ„์ž„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์œ„์—์„œ ์„ค๋ช…ํ•œ Glide๋ฅผ ํฌํ•จํ•ด ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋ฏธ์ง€๋กœ๋” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ข…๋ฅ˜๋Š” ๋ฌด์—‡์ด ์žˆ์œผ๋ฉฐ, ๊ฐ๊ฐ ์–ด๋–ค ์ฐจ์ด์ ์ด ์žˆ๋Š”์ง€ ๋‹ค์Œ ํฌ์ŠคํŠธ์—์„œ ์‚ดํŽด๋ณด์ž.

profile
android developer @bucketplace
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€