Search
moon
sun

JVM TLAB (Thread Local Allocation Buffer)

/

1. TLAB์ด ์™œ ํ•„์š”ํ•œ๊ฐ€?

Java์—์„œ new ํ‚ค์›Œ๋“œ๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด JVM์€ Heap ๋ฉ”๋ชจ๋ฆฌ์— ๊ณต๊ฐ„์„ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ Young Generation์˜ Eden ์˜์—ญ์— ๊ฐ์ฒด๊ฐ€ ๋จผ์ € ๋†“์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊น๋‹ˆ๋‹ค. ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์„ ์š”์ฒญํ•˜๋ฉด ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
Thread A โ”€โ”€โ–ถ Eden [____ํ• ๋‹น ํฌ์ธํ„ฐ____] โ—€โ”€โ”€ Thread B โ†‘ ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ์œ„์น˜ ์š”์ฒญ!
Plain Text
๋ณต์‚ฌ
์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋‹จ์ˆœํ•œ ๋ฐฉ๋ฒ•์€ ๋ฝ(Lock)์œผ๋กœ ๋™๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ, ๊ฐ์ฒด ์ƒ์„ฑ์ด ๋งค์šฐ ๋นˆ๋ฒˆํ•œ Java ํŠน์„ฑ์ƒ ๋ฝ ๊ฒฝํ•ฉ์ด ๊ทน์‹ฌํ•œ ์„ฑ๋Šฅ ๋ณ‘๋ชฉ์ด ๋ฉ๋‹ˆ๋‹ค.

2. TLAB์˜ ๊ฐœ๋…

TLAB(Thread Local Allocation Buffer)์€ Eden ๋‚ด๋ถ€์—์„œ ํŠน์ • ์Šค๋ ˆ๋“œ์—๊ฒŒ ์ „์šฉ์œผ๋กœ ํ• ๋‹น๋œ ์˜์—ญ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ์˜์—ญ์—๋Š” ์˜ค์ง ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์ƒˆ ๊ฐ์ฒด๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ ์Šค๋ ˆ๋“œ๋Š” ์ž์‹ ๋งŒ์˜ TLAB์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Eden Space โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Thread-1 โ”‚ โ”‚ Thread-2 โ”‚ โ”‚ Thread-3 โ”‚ โ”‚ โ”‚ โ”‚ TLAB โ”‚ โ”‚ TLAB โ”‚ โ”‚ TLAB โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ ๊ณต์œ  Eden ์˜์—ญ (Slow Allocation) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
Plain Text
๋ณต์‚ฌ

3. ํ•ต์‹ฌ ๋™์ž‘ ๋ฐฉ์‹: Pointer Bump Allocation

๊ฐ€์žฅ ๋นˆ๋ฒˆํ•œ "์ •์ƒ" ๊ฒฝ๋กœ๋Š” ๋‹จ์ˆœํžˆ TLAB์˜ ํ˜„์žฌ ์ปค์„œ(ํฌ์ธํ„ฐ)์— ๊ฐ์ฒด ํฌ๊ธฐ๋ฅผ ๋”ํ•˜๊ณ  ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๋•Œ๋ฌธ์— ์ด ๋ฐฉ์‹์„ **"ํฌ์ธํ„ฐ ๋ฒ”ํ”„ ํ• ๋‹น(Pointer Bump Allocation)"**์ด๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค.
// TLAB ๋‚ด ๊ฐ์ฒด ํ• ๋‹น ์˜์‚ฌ ์ฝ”๋“œ Object allocate(size) { if (tlab.top + size <= tlab.end) { Object obj = tlab.top; tlab.top += size; // ํฌ์ธํ„ฐ๋งŒ ์ด๋™! ๋™๊ธฐํ™” ๋ถˆํ•„์š” return obj; } // TLAB์ด ๋ถ€์กฑํ•˜๋ฉด ๋‹ค๋ฅธ ์ฒ˜๋ฆฌ }
Java
๋ณต์‚ฌ
์ด ๋ฐฉ์‹์˜ ํ•ต์‹ฌ์€ ๋™๊ธฐํ™”๊ฐ€ ์ „ํ˜€ ํ•„์š” ์—†๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž์‹ ๋งŒ์˜ ์˜์—ญ์—์„œ๋งŒ ํฌ์ธํ„ฐ๋ฅผ ์›€์ง์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

4. TLAB ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•  ๋•Œ: 4๊ฐ€์ง€ ์„ ํƒ์ง€

๊ฐ์ฒด๋ฅผ ํ• ๋‹นํ•˜๋ ค๋Š”๋ฐ TLAB์— ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•˜๋ฉด JVM์€ ๋„ค ๊ฐ€์ง€ ์„ ํƒ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ์งธ๋กœ ํ•ด๋‹น ์Šค๋ ˆ๋“œ๋ฅผ ์œ„ํ•ด ์ƒˆ TLAB ๊ณต๊ฐ„์„ ํ• ๋‹น(TLAB ํ™•์žฅ), ๋‘˜์งธ๋กœ TLAB ์™ธ๋ถ€(๊ณต์œ  Eden ์˜์—ญ)์—์„œ ํ•ด๋‹น ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹น, ์…‹์งธ๋กœ GC๋ฅผ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ํšŒ์ˆ˜ ์‹œ๋„, ๋„ท์งธ๋กœ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์— ์‹คํŒจํ•˜๊ณ  ์—๋Ÿฌ๋ฅผ ๋˜์ง€๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋„ค ๋ฒˆ์งธ๋Š” ์ตœ์•…์˜ ๊ฒฝ์šฐ์ด๋ฉฐ JVM์€ ์ด๋ฅผ ์ตœ๋Œ€ํ•œ ํ”ผํ•˜๋ ค ํ•ฉ๋‹ˆ๋‹ค.

TLAB Retirement (์€ํ‡ด) ๋ฉ”์ปค๋‹ˆ์ฆ˜

TLAB ๋‚จ์€ ๊ณต๊ฐ„์ด **์ž„๊ณ„๊ฐ’(Refill Waste)**๋ณด๋‹ค ์ž‘์œผ๋ฉด, JVM์€ ํ˜„์žฌ TLAB์„ "์€ํ‡ด(retire)"์‹œํ‚ค๊ณ  ์ƒˆ TLAB์„ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ ๋‚จ์€ ๊ณต๊ฐ„์ด ์ž„๊ณ„๊ฐ’๋ณด๋‹ค ํฌ๋ฉด, ํฐ ๊ฐ์ฒด๋ฅผ TLAB ์™ธ๋ถ€(๊ณต์œ  Eden)์— ์ง์ ‘ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค(Slow Allocation).
๊ธฐ๋ณธ์ ์œผ๋กœ ์ด ์ž„๊ณ„๊ฐ’์€ TLAB ํฌ๊ธฐ์˜ 1%์ด๋ฉฐ, -XX:TLABWasteTargetPercent=N ํ”Œ๋ž˜๊ทธ๋กœ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค(๊ธฐ๋ณธ๊ฐ’ 1). Slow Allocation์ด ์ฆ๊ฐ€ํ• ์ˆ˜๋ก ๋” ๋งŽ์€ Slow Allocation์„ ์ค„์ด๊ธฐ ์œ„ํ•ด JVM์€ ์ด ๊ฐ’์„ -XX:TLABWasteIncrement=N์— ์˜ํ•ด ๊ฒฐ์ •๋œ ๊ฐ’๋งŒํผ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค(๊ธฐ๋ณธ๊ฐ’ 4).

5. TLAB ํฌ๊ธฐ ๊ฒฐ์ • ๋ฐฉ์‹

๊ธฐ๋ณธ์ ์œผ๋กœ TLAB์€ ๊ฐ ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ๋™์ ์œผ๋กœ ํฌ๊ธฐ๊ฐ€ ์กฐ์ •๋ฉ๋‹ˆ๋‹ค. TLAB ํฌ๊ธฐ๋Š” Eden์˜ ํฌ๊ธฐ, ์Šค๋ ˆ๋“œ ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  ์Šค๋ ˆ๋“œ๋ณ„ ํ• ๋‹น ์†๋„๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์žฌ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.
์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๋Š”:
โ€ข
์ด๋ฏธ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋“ค์€ Eden ์˜์—ญ์— ๊ทธ๋Œ€๋กœ ๋‚จ์•„ GC๊ฐ€ ๊ด€๋ฆฌ
โ€ข
๋‚จ์€ ๋ฏธ์‚ฌ์šฉ ๊ณต๊ฐ„์€ Eden์— ๋ฐ˜ํ™˜๋˜๋ฉฐ, JVM์ด GC๊ฐ€ ํž™์„ ํŒŒ์‹ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋”๋ฏธ(Filler) ๊ฐ์ฒด๋กœ ์ฑ„์›๋‹ˆ๋‹ค

6. ์„ฑ๋Šฅ ํšจ๊ณผ

TLAB ์—†์ด ๋‹จ์ผ ์Šค๋ ˆ๋“œ์—์„œ๋„ CAS(Compare-And-Swap) ์›์ž ์—ฐ์‚ฐ์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— TLAB์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๋Œ€๋น„ ์„ฑ๋Šฅ์ด ์ ˆ๋ฐ˜ ์ˆ˜์ค€์— ๊ทธ์นฉ๋‹ˆ๋‹ค. x86 ์ฝ”์–ด์—์„œ ์ผ๋ฐ˜์ ์ธ store๋Š” ์ฆ‰์‹œ ํ”„๋กœ์„ธ์„œ ์บ์‹œ์— ๋„๋‹ฌํ•˜์ง€ ์•Š๊ณ  "์Šคํ† ์–ด ๋ฒ„ํผ"์— ๋จผ์ € ์“ฐ์ด๊ณ  ์‹คํ–‰์ด ๊ณ„์†๋˜๋Š” ๋ฐ˜๋ฉด, CAS ์—ฐ์‚ฐ์€ ๊ทธ๋ ‡์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
์‹ค์ œ ๋ฒค์น˜๋งˆํฌ์—์„œ TLAB ํ™œ์„ฑํ™” ์‹œ ๋‹จ์ผ ์Šค๋ ˆ๋“œ๋กœ๋„ ์ดˆ๋‹น ์•ฝ 2.5GB/s์˜ ํ• ๋‹น ์†๋„, 16๋ฐ”์ดํŠธ ๊ฐ์ฒด ๊ธฐ์ค€ ์ดˆ๋‹น 1์–ต 6์ฒœ๋งŒ ๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

7. ์ฃผ์š” JVM ํ”Œ๋ž˜๊ทธ ์ •๋ฆฌ

ํ”Œ๋ž˜๊ทธ
์„ค๋ช…
๊ธฐ๋ณธ๊ฐ’
-XX:+UseTLAB
TLAB ํ™œ์„ฑํ™”
true (๊ธฐ๋ณธ ํ™œ์„ฑํ™”)
-XX:-UseTLAB
TLAB ๋น„ํ™œ์„ฑํ™”
-
-XX:TLABSize=N
TLAB ์ดˆ๊ธฐ ํฌ๊ธฐ ์„ค์ •
0 (์ž๋™)
-XX:MinTLABSize=N
TLAB ์ตœ์†Œ ํฌ๊ธฐ
-
-XX:MaxTLABSize=N
TLAB ์ตœ๋Œ€ ํฌ๊ธฐ
-
-XX:TLABWasteTargetPercent=N
Slow Allocation ์ž„๊ณ„๊ฐ’ (%)
1
-XX:TLABWasteIncrement=N
Slow Alloc ๋ฐœ์ƒ ์‹œ ์ž„๊ณ„๊ฐ’ ์ฆ๊ฐ€๋Ÿ‰
4
-XX:TLABRefillWasteFraction=N
TLAB ์žฌ์ถฉ์ „ ๋‚ญ๋น„ ๋น„์œจ
-

8. TLAB ํ†ต๊ณ„ ํ™•์ธ ๋ฐฉ๋ฒ•

GC ๋กœ๊ทธ์—์„œ TLAB ๋™์ž‘์„ ๊ด€์ฐฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
# GC ๋กœ๊ทธ ํ™œ์„ฑํ™” -XX:+PrintTLAB -Xlog:gc+tlab=trace # JDK 9 ์ด์ƒ
Bash
๋ณต์‚ฌ
๋กœ๊ทธ ์˜ˆ์‹œ ํ•ด์„:
TLAB: gc thread: 0x... [id: 1234] desired_size: 491KB slow allocs: 7 waste 44% refills: 111 waste: 0.1%
Plain Text
๋ณต์‚ฌ
โ€ข
slow allocs: TLAB ์™ธ๋ถ€ ํ• ๋‹น ํšŸ์ˆ˜ โ†’ ๋†’์œผ๋ฉด ๋ฌธ์ œ
โ€ข
refills: TLAB ์žฌ์ถฉ์ „ ํšŸ์ˆ˜
โ€ข
waste: ๋‚ญ๋น„ ๋น„์œจ โ†’ ๋‚ฎ์„์ˆ˜๋ก ํšจ์œจ์ 

9. ์‹ค๋ฌด์—์„œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ 

TLAB ์™ธ๋ถ€ ํ• ๋‹น(Slow Allocation)์ด ๋งŽ์€ ๊ฒฝ์šฐ์˜ ์›์ธ๊ณผ ํ•ด๊ฒฐ์ฑ…:
1.
ํฐ ๋ฐฐ์—ด/๊ฐ์ฒด: TLAB์— ๋งž์ง€ ์•Š๋Š” ํฐ ๊ฐ์ฒด๋Š” ๋ฌด์กฐ๊ฑด ๊ณต์œ  Eden์— ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. โ†’ ๊ฐ์ฒด ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ฑฐ๋‚˜ MaxTLABSize๋ฅผ ๋Š˜๋ ค๋ณผ ๊ฒƒ
2.
์Šค๋ ˆ๋“œ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์Œ: ์Šค๋ ˆ๋“œ ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๊ฐ TLAB ํฌ๊ธฐ๊ฐ€ ์ž‘์•„์ ธ ์ž์ฃผ ์žฌ์ถฉ์ „์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. โ†’ ์Šค๋ ˆ๋“œ ํ’€ ํฌ๊ธฐ ์กฐ์ •
3.
ํ• ๋‹น ์†๋„๊ฐ€ ์ง€๋‚˜์น˜๊ฒŒ ๋†’์Œ: GC ํŠœ๋‹๊ณผ ํ•จ๊ป˜ Eden ํฌ๊ธฐ(Xmn) ์กฐ์ •์„ ๊ณ ๋ ค
ํ•ต์‹ฌ ์ •๋ฆฌ: TLAB์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๊ณ  JVM์ด ์ž๋™์œผ๋กœ ์ตœ์ ํ™”ํ•˜๋ฏ€๋กœ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๊ฑด๋“œ๋ฆด ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Slow Allocation ๋น„์œจ์ด ๋†’๊ฑฐ๋‚˜ ํ• ๋‹น ๊ด€๋ จ ์„ฑ๋Šฅ ์ด์Šˆ๊ฐ€ ์žˆ์„ ๋•Œ, TLAB ํ†ต๊ณ„๋ฅผ ๋ถ„์„ํ•˜์—ฌ ๊ฐ์ฒด ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ฑฐ๋‚˜ ์Šค๋ ˆ๋“œ/ํž™ ํŠœ๋‹์„ ํ•˜๋Š” ์ ‘๊ทผ์ด ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.