๋ฐฐ๊ฒฝ
์ผ๋ง ์ ์ ๋ฌด์์ ์บ์๋ฅผ ์ ์ฉํ๋๋ฐ๋ ์ฑ๋ฅ์ด ๋์์ง์ง ์๋ ์ด์ํ ์ํฉ์ ๊ฒช์๋ค.
์บ์ ํํธ๋ ์ ์์ด์๋ค. ๊ทผ๋ฐ ๋๋ ธ๋ค.
๋ฌธ์ ๋ 8500๊ฐ์ง๋ฆฌ Map์ ์บ์์์ ๊บผ๋ด๋ ๋ก์ง์ ์์๋ค. getDataMap()์ ๋ถ๋ช
์บ์์์ ์๋ตํ๊ณ ์์๋๋ฐ, ์์ฒญ์ด ๋ชฐ๋ฆด ๋๋ง๋ค ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ๋ณต๋๋ค.
@Cacheable(value = "dataCache", key = "'dataMap'")
public Map<String, String> getDataMap() {
return dataRepository.findAll();
}
์์ธ์ ํ๊ณ ๋ค๋ค ๋ณด๋ ๋ด๊ฐ ์บ์ ์ค์ ํ์ผ์์ ๋ฌด์ฌ์ฝ <offheap>์ ์ฐ๊ณ ์์๋ค๋ ๊ฑธ ์๊ฒ ๋๋ค.
<cache alias="dataCache">
<resources>
<offheap unit="MB">50</offheap>
</resources>
</cache>
๊ทธ๋ฆฌ๊ณ ๊ทธ๋ ์ฒ์์ผ๋ก ์ ๋๋ก ์ดํดํ๋ค. Heap ์บ์์ Offheap ์บ์๋ ๋์ ๋ฐฉ์ ์์ฒด๊ฐ ๋ค๋ฅด๋ค๋ ๊ฑธ.
์ด ๊ธ์ ๊ทธ ๊ณผ์ ์์ ์ ๋ฆฌํ ๋ด์ฉ์ด๋ค.
Heap๊ณผ Offheap์ ์ฐจ์ด
JVM ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ
๋ ์บ์๋ฅผ ์ดํดํ๋ ค๋ฉด JVM์ ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋จผ์ ๋ด์ผ ํ๋ค.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ JVM Process โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Heap ์์ญ โ โ Offheap ์์ญ โ โ
โ โ (GC ๊ด๋ฆฌ ๋์) โ โ (GC ๊ด๋ฆฌ ์ธ๋ถ) โ โ
โ โ โ โ โ โ
โ โ Java๊ฐ ์์ฑํ โ โ Ehcache๊ฐ โ โ
โ โ ๋ชจ๋ ๊ฐ์ฒด โ โ ์ง์ ๊ด๋ฆฌํ๋ โ โ
โ โ โ โ ๋ค์ดํฐ๋ธ ๋ฉ๋ชจ๋ฆฌ โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- Heap:
new HashMap()๊ฐ์ด Java๊ฐ ์์ฑํ๋ ๋ชจ๋ ๊ฐ์ฒด๊ฐ ์ฌ๋ผ๊ฐ๋ ๊ณต๊ฐ. GC๊ฐ ๊ด๋ฆฌํ๋ค. - Offheap: JVM ์ธ๋ถ์ ๋ค์ดํฐ๋ธ ๋ฉ๋ชจ๋ฆฌ. GC์ ๊ด๋ฆฌ ๋ฒ์ ๋ฐ์ด๋ค.
Heap ์บ์์ ๋์ ๋ฐฉ์
์์ฒญ → Ehcache → HashMap ๊ฐ์ฒด ์ฐธ์กฐ(์ฃผ์) ๋ฐํ → ๋
Heap ์บ์๋ ๊ฐ์ฒด๋ฅผ Heap์ ๊ทธ๋๋ก ์ฌ๋ ค๋๊ณ , ์บ์ ํํธ ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ง ์ ๋ฌํ๋ค. ๋ณต์ฌ๋, ๋ณํ๋ ์๋ค.
๊ทธ๋ฅ "๊ฑฐ๊ธฐ ์์ด" ํ๊ณ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฒ๊ณผ ๊ฐ๋ค.
Offheap ์บ์์ ๋์ ๋ฐฉ์
Offheap์ ๋ค๋ฅด๋ค.
[์ ์ฅ ์]
HashMap ๊ฐ์ฒด → ์ง๋ ฌํ → [๋ฐ์ดํธ ๋ฐฐ์ด] → Offheap ๋ฉ๋ชจ๋ฆฌ ์ ์ฅ
[์กฐํ ์]
Offheap ๋ฉ๋ชจ๋ฆฌ → [๋ฐ์ดํธ ๋ฐฐ์ด] → ์ญ์ง๋ ฌํ → ์ HashMap ๊ฐ์ฒด ์์ฑ
์บ์ ํํธ๊ฐ ์ผ์ด๋ ๋๋ง๋ค ์ญ์ง๋ ฌํ๊ฐ ๋ฐ์ํ๋ค. ์ด ๋ถ๋ถ์ด ํต์ฌ์ด๋ค.
์ Offheap์ ์ง๋ ฌํ๊ฐ ํ์ํ ๊น?
JVM Heap์ Java ๊ฐ์ฒด๋ ๋จ์ํ ๋ฐ์ดํธ ๋ฉ์ด๋ฆฌ๊ฐ ์๋๋ค.
HashMap ๊ฐ์ฒด (JVM Heap ๋ด๋ถ)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Object Header โ ← ํด๋์ค ๋ฉํ๋ฐ์ดํฐ ํฌ์ธํฐ
โ (class pointer, hash, lock...) โ GC ์ ๋ณด, ๋๊ธฐํ ๋ฝ ๋ฑ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ table (Entry[] ์ฐธ์กฐ) โ → ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋
โ size: 8500 โ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์(์ฐธ์กฐ)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
↓
โโโโโโโโโโโโโโโโโโโ
โ Entry ๊ฐ์ฒด๋ค โ
โ key → "item1" โ
โ val → "100" โ
โโโโโโโโโโโโโโโโโโโ
๊ฐ์ฒด๋ค์ด ๋ฉ๋ชจ๋ฆฌ ์ฃผ์(์ฐธ์กฐ) ๋ก ์๋ก ์ฐ๊ฒฐ๋ ๊ทธ๋ํ ๊ตฌ์กฐ๋ค.
์ด ๊ตฌ์กฐ๋ฅผ Offheap์ผ๋ก ๊ทธ๋๋ก ๊ฐ์ ธ๊ฐ ์ ์๋ ์ด์ ๊ฐ ์ธ ๊ฐ์ง ์๋ค.
์ด์ 1 — ์ฐธ์กฐ(ํฌ์ธํฐ)๋ JVM Heap ์์์๋ง ์ ํจํ๋ค
JVM Heap Offheap (Native Memory)
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ
โ HashMap โ โ โ
โ table → 0x4A2F โโโโโโโโโโ→โ 0x4A2F ??? โ
โ โ โ (์ด ์ฃผ์๊ฐ ์ฌ๊ธฐ์ โ
โโโโโโโโโโโโโโโโ โ ์๋ฌด ์๋ฏธ๊ฐ ์์) โ
โโโโโโโโโโโโโโโโโโโโโโโโ
์ด์ 2 — GC๊ฐ ๊ฐ์ฒด๋ฅผ ์ด๋์ํจ๋ค
GC ์คํ ์ GC ์คํ ํ (๋ฉ๋ชจ๋ฆฌ ์์ถ)
HashMap: 0x4A2F → HashMap: 0x1B3C (์ฃผ์๊ฐ ๋ฐ๋!)
Offheap์ ์ฃผ์๋ฅผ ์ ์ฅํด๋๋ค๊ฐ GC ํ์ ๊บผ๋ด๋ฉด ์๋ฑํ ๊ณณ์ ๊ฐ๋ฆฌํค๊ฒ ๋๋ค.
์ด์ 3 — Object Header๋ JVM ์ ์ฉ ๊ตฌ์กฐ๋ค
Object Header์๋ ํด๋์ค ์ ๋ณด ํฌ์ธํฐ, GC ๋งํน ๋นํธ, ๋๊ธฐํ ๋ฝ ์ ๋ณด๊ฐ ๋ด๊ฒจ ์๋๋ฐ, JVM ์ธ๋ถ์์๋ ํด์์ด ๋ถ๊ฐ๋ฅํ๋ค.
๊ทธ๋์ ์ง๋ ฌํ๋ก "์ฃผ์ ์๋ ์์ ๋ฐ์ดํฐ"๋ก ๋ณํํด์ ์ ์ฅํ๋ ๊ฒ์ด๋ค.
์ง๋ ฌํ = ์ฐธ์กฐ ๊ทธ๋ํ๋ฅผ ๋๊ณ → ํํํ ๋ฐ์ดํธ ๋ฐฐ์ด๋ก
HashMap { "item1"→"100", "item2"→"200" }
(์ฐธ์กฐ๋ก ์ฐ๊ฒฐ๋ ๊ฐ์ฒด ๊ทธ๋ํ)
↓ ์ง๋ ฌํ
[ํ์
์ ๋ณด | "item1" | "100" | "item2" | "200" | ...]
(์๊ธฐ์๊ฒฐ์ ์ธ ์์ ๋ฐ์ดํธ ๋ฐฐ์ด)
↓ Offheap ์ ์ฅ ๊ฐ๋ฅ
์ญ์ง๋ ฌํ ์์๋ ์ด ๋ฐ์ดํธ ๋ฐฐ์ด์ ์ฝ์ด JVM Heap์ ์ ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๋ค.
์ ๋ฆฌ — ์บ์ ํํธ๋ผ๋ Offheap์ ํญ์ ์ญ์ง๋ ฌํํ๋ค
๋ด ์ผ์ด์ค์์ ๋ฌธ์ ๊ฐ ๋๋ ์ด์ ๊ฐ ๋ฐ๋ก ์ด๊ฑฐ๋ค.
[Offheap ์บ์ ์กฐํ ์]
Offheap ๋ฉ๋ชจ๋ฆฌ → [๋ฐ์ดํธ ๋ฐฐ์ด] → ์ญ์ง๋ ฌํ → ์ HashMap ๊ฐ์ฒด ์์ฑ
↑ ํํธ๋ง๋ค ์ด ๋น์ฉ ๋ฐ๋ณต ๋ฐ์
processRequest()๋ ์์ฒญ๋ง๋ค ํธ์ถ๋๋ค. 8500๊ฐ์ง๋ฆฌ Map์ ์์ฒญ๋ง๋ค ์ญ์ง๋ ฌํํ๋ฉด ๋น์ฐํ ๋๋ฆฌ๋ค.
Heap vs Offheap ์ ํ ๊ธฐ์ค
| Heap ์ ๋ฆฌ | Offheap ์ ๋ฆฌ | |
|---|---|---|
| ๊ฐ์ฒด ํฌ๊ธฐ | ์์ ๋ (~์ MB ์ดํ) | ๋งค์ฐ ํด ๋ (์๋ฐฑ MB~GB) |
| ์กฐํ ๋น๋ | ๋์ ๋ | ๋ฎ์ ๋ |
| GC ์ํฉ | Stop-the-world ๋ฌธ์ ์์ ๋ | GC ๋ถ๋ด์ด ์ฌํ ๋ |
| Heap ๋ฉ๋ชจ๋ฆฌ | ์ฌ์ ์์ ๋ | ๋ถ์กฑํ ๋ |
๋ด ์ผ์ด์ค๋ ์ฝ 300KB์ง๋ฆฌ Map, ๊ณ ๋น๋ ์กฐํ → Heap์ด ์ ํฉํ ์ํฉ์ด์๋ค.
์๋ฐ ์คํ๋ง์์์ ๊ตฌํ
Ehcache ์ค์ ์์ <offheap>์ <heap>์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ๋ง์ผ๋ก ํด๊ฒฐ๋๋ค.
<cache alias="dataCache">
<key-type>java.lang.String</key-type>
<value-type>java.util.HashMap</value-type>
<expiry>
<ttl unit="hours">1</ttl>
</expiry>
<resources>
<heap unit="entries">1</heap>
</resources>
</cache>
unit="entries"๋ ๋ฐ์ดํธ ํฌ๊ธฐ๊ฐ ์๋ ํค-๊ฐ ์์ ๊ฐ์๋ก ์ฉ๋์ ์ ํํ๋ ๋จ์๋ค. ์บ์ ํค๊ฐ ๊ณ ์ ๋ฌธ์์ด ํ๋๋ฟ์ด๋ผ ์ํธ๋ฆฌ๊ฐ ํญ์ 1๊ฐ → entries = 1๋ก ์ค์ ํ๋ค.
@Cacheable(value = "dataCache", key = "'dataMap'")
// ↑ ํญ์ ๊ณ ์ → ์ํธ๋ฆฌ 1๊ฐ
public Map<String, String> getDataMap() {
return dataRepository.findAll();
}
์ด๊ฑธ๋ก ์บ์ ํํธ ์ ์ญ์ง๋ ฌํ ์์ด ๋ฐ๋ก ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๋ฐํํ๊ฒ ๋๊ณ , ์ฑ๋ฅ ์ด์๊ฐ ํด๊ฒฐ๋๋ค.
๋ง๋ฌด๋ฆฌ
"์บ์ ํํธ = ๋น ๋ฆ"์ด๋ผ๊ณ ๋ง ์๊ฐํ๊ณ ์์๋๋ฐ, Offheap์ ๊ฒฝ์ฐ ํํธ ์์๋ ์ญ์ง๋ ฌํ ๋น์ฉ์ด ๋งค๋ฒ ๋ฐ์ํ๋ค๋ ๊ฑธ ์ฒ์์ผ๋ก ์ ๋๋ก ์ดํดํ ๊ณ๊ธฐ์๋ค.
์ค์ ํ์ผ ํ ์ค(<offheap> → <heap>)๋ง ๋ฐ๊ฟจ๋๋ฐ ์ฑ๋ฅ์ด ๊ฐ์ ๋๋ค. ๊ทธ ํ ์ค์ ์๋ฏธ๋ฅผ ๋ชฐ๋๋ ๊ฒ ๋ฌธ์ ์๋ค.
์บ์๋ฅผ ์ ํํ ๋๋ ๊ฐ์ฒด ํฌ๊ธฐ์ ์กฐํ ๋น๋๋ฅผ ๊ธฐ์ค์ผ๋ก ์๊ฐํด์ผ๊ฒ ๋ค๋ ๊ตํ์ ์ป์๋ค.