๐ŸŽฏ1์ฃผ์ฐจ Unit 5.3 โ€” GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ 4๊ฐ€์ง€

Psjยท4์ผ ์ „

F-lab

๋ชฉ๋ก ๋ณด๊ธฐ
39/52

๐ŸŽฏ Unit 5.3 โ€” GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ 4๊ฐ€์ง€

F-lab Java 1์ฃผ์ฐจ / Phase 5 / Unit 5.3 ๋ณธ๊ฒฉ ํ•™์Šต ์ž๋ฃŒ
9-์„น์…˜ ๋งˆ์Šคํ„ฐ ํ”„๋กฌํ”„ํŠธ ํ˜•์‹์œผ๋กœ ๊นŠ์ด ํŒŒํ—ค์นœ๋‹ค.

์„ ์ˆ˜ ์ง€์‹: Unit 5.2 (Heap์˜ ์„ธ๋Œ€ ๊ตฌ์กฐ)
๋‹ค์Œ Unit: 5.4 โ€” GC ์ข…๋ฅ˜์™€ ์„ ํƒ ๊ธฐ์ค€

์ด Unit์˜ ์˜๋ฏธ: GC ์˜ 4๊ฐ€์ง€ ํ•ต์‹ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋น„๊ต.
๊ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๋™์ž‘ ์›๋ฆฌ, ์žฅ๋‹จ์ , ์ž๋ฐ”๊ฐ€ ๋ฌด์—‡์„ ์ฑ„ํƒํ–ˆ๋Š”์ง€.
๋ฉด์ ‘์—์„œ "์™œ ์ž๋ฐ”๋Š” Reference Counting ์•ˆ ์“ฐ๋‚˜์š”?" ๊ฐ™์€ ๊นŠ์ด ์žˆ๋Š” ์งˆ๋ฌธ ๋Œ€๋น„.


๐ŸŒ 1. ์„ธ์ƒ ์† ๋น„์œ 

4๊ฐ€์ง€ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ = "4๊ฐ€์ง€ ์ฒญ์†Œ ๋ฐฉ์‹"

ํฐ ์‚ฌ๋ฌด์‹ค์„ ์ฒญ์†Œํ•˜๋Š” 4๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์ƒ์ƒํ•ด๋ณด์„ธ์š”.

๋ฐฉ์‹ 1 โ€” "๋ฐฉ๋ฌธ์ž ์นด์šดํ„ฐ" (Reference Counting)

  • ๋ชจ๋“  ๋ฌผ๊ฑด์— ๋ฐฉ๋ฌธ์ž ์ˆ˜ ์นด์šดํ„ฐ ๋ถ€์ฐฉ
  • ๋ˆ„๊ตฐ๊ฐ€ ์‚ฌ์šฉ ์‹œ์ž‘ โ†’ +1
  • ๋ˆ„๊ตฐ๊ฐ€ ์‚ฌ์šฉ ๋ โ†’ -1
  • ์นด์šดํ„ฐ 0 โ†’ ์ฆ‰์‹œ ๋ฒ„๋ฆผ

์žฅ์ : ์ฆ‰๊ฐ์ , ๋ฉˆ์ถค ์—†์Œ
๋‹จ์ : ์ˆœํ™˜ ์ฐธ์กฐ ๋ฌธ์ œ โ€” A ๊ฐ€ B ์‚ฌ์šฉ, B ๊ฐ€ A ์‚ฌ์šฉ โ†’ ๋‘˜ ๋‹ค ์•ˆ ๋ฒ„๋ ค์ง โŒ


๋ฐฉ์‹ 2 โ€” "์‚ฌ์šฉ ์ค‘ ํ‘œ์‹œ" (Mark-and-Sweep)

  • ์ฒญ์†Œ ์‹œ๊ฐ„์— ๋ชจ๋“  ์ง์› ์ •์ง€ (STW)
  • ์‚ฌ์šฉ ์ค‘์ธ ๋ฌผ๊ฑด์— ํฌ์ŠคํŠธ์ž‡ ๋ถ™์ด๊ธฐ (Mark)
  • ํฌ์ŠคํŠธ์ž‡ ์—†๋Š” ๊ฒƒ ๋ชจ๋‘ ๋ฒ„๋ฆผ (Sweep)
  • ๋‹ค์‹œ ์ผ ์‹œ์ž‘

์žฅ์ : ์ˆœํ™˜ ์ฐธ์กฐ ํ•ด๊ฒฐ, ๋‹จ์ˆœ
๋‹จ์ : STW, ๋นˆ ์ž๋ฆฌ ๊ณณ๊ณณ (๋‹จํŽธํ™”)


๋ฐฉ์‹ 3 โ€” "์‚ฌ์šฉ ์ค‘ ํ‘œ์‹œ + ์ •๋ฆฌ" (Mark-Sweep-Compact)

  • Mark-Sweep ์˜ ๊ฐ™์€ ์‹œ์ž‘
  • ์ถ”๊ฐ€๋กœ ๋‚จ์€ ๋ฌผ๊ฑด๋“ค์„ ํ•œ์ชฝ์œผ๋กœ ์ •๋ ฌ
  • ๋นˆ ๊ณต๊ฐ„ ํ•œ์ชฝ์— ๋ชจ์Œ

์žฅ์ : ๋‹จํŽธํ™” ํ•ด์†Œ
๋‹จ์ : ์ •๋ฆฌ ๋น„์šฉ, ๊ฐ์ฒด ์ด๋™


๋ฐฉ์‹ 4 โ€” "์„ธ๋Œ€๋ณ„ ์ฒญ์†Œ" (Generational)

  • ์‹ ์ž… ์ฑ…์ƒ (Eden) ์ž์ฃผ ์ฒญ์†Œ
  • ์ผ๋ฐ˜ ์ฑ…์ƒ (Survivor) ๊ฐ€๋” ์ฒญ์†Œ
  • ์ž„์› ์ฑ…์ƒ (Old) ๊ฑฐ์˜ ์•ˆ ์ฒญ์†Œ
  • ๊ฐ์ž ๋‹ค๋ฅธ ์ฒญ์†Œ ๋ฐฉ์‹

์žฅ์ : ํšจ์œจ์ 
๋‹จ์ : ๊ตฌ์กฐ ๋ณต์žก

โ†’ ์ด๊ฒŒ 4๊ฐ€์ง€ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜. ์ž๋ฐ”๋Š” ๋ฐฉ์‹ 4 (Generational) ์ฑ„ํƒ.


ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

"GC ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ '์“ฐ๋ ˆ๊ธฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์‹๋ณ„ํ•˜๊ณ  ์ œ๊ฑฐํ• ๊นŒ' ์˜ 4๊ฐ€์ง€ ๋‹ต์ด๋‹ค."

๊ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ trade-off:

  • ์ˆœํ™˜ ์ฐธ์กฐ ์ฒ˜๋ฆฌ?
  • STW ๊ธธ์ด?
  • ๋‹จํŽธํ™”?
  • ํšจ์œจ์„ฑ?

๋น„์œ  ์ •๋ฆฌ:

๋น„์œ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜์žฅ์ ๋‹จ์ 
๋ฐฉ๋ฌธ์ž ์นด์šดํ„ฐReference Counting์ฆ‰์‹œ, ๋ฉˆ์ถค X์ˆœํ™˜ ์ฐธ์กฐ
ํฌ์ŠคํŠธ์ž‡ ํ‘œ์‹œMark-Sweep๋‹จ์ˆœ๋‹จํŽธํ™”
ํ‘œ์‹œ + ์ •๋ฆฌMark-Sweep-Compact์••์ถ•์ด๋™ ๋น„์šฉ
์„ธ๋Œ€๋ณ„ ์ฒญ์†ŒGenerationalํšจ์œจ๋ณต์žก

๐Ÿ”ฅ 2. ํƒ„์ƒ ๋ฐฐ๊ฒฝ

"์“ฐ๋ ˆ๊ธฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์•Œ์•„๋‚ผ๊นŒ?" โ€” ๊ฐ€์žฅ ๋ณธ์งˆ์  ์งˆ๋ฌธ

GC ์˜ ํ•ต์‹ฌ ๋ฌธ์ œ:

"Heap ์˜ ์–ด๋–ค ๊ฐ์ฒด๊ฐ€ ์‚ฌ์šฉ ์ค‘ ์ด๊ณ , ์–ด๋–ค ๊ฒŒ ์“ฐ๋ ˆ๊ธฐ ์ธ๊ฐ€?"

์ด ์งˆ๋ฌธ์— ๋‹ตํ•˜๋Š” ๋ฐฉ์‹์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์˜ ์ฐจ์ด.


์•Œ๊ณ ๋ฆฌ์ฆ˜ 1 โ€” Reference Counting (1950s) โญ

๊ฐ€์žฅ ์ง๊ด€์ ์ธ ๋ฐฉ์‹, 1950๋…„๋Œ€ LISP์—์„œ ์ฒ˜์Œ ๋“ฑ์žฅ.

์•„์ด๋””์–ด:

  • ๋ชจ๋“  ๊ฐ์ฒด์— ์ฐธ์กฐ ์นด์šดํŠธ ํ•„๋“œ ์ถ”๊ฐ€
  • ์ฐธ์กฐ +1 / -1 โ†’ ์นด์šดํŠธ ์ถ”์ 
  • ์นด์šดํŠธ 0 โ†’ ์ฆ‰์‹œ ํšŒ์ˆ˜

์žฅ์ :

  • ์ฆ‰๊ฐ์  (0์ด ๋˜๋Š” ์ˆœ๊ฐ„ ํšŒ์ˆ˜)
  • STW ์—†์Œ
  • ๋‹จ์ˆœํ•œ ๊ฐœ๋…

๋ฌธ์ œ ๋ฐœ๊ฒฌ โ€” ์ˆœํ™˜ ์ฐธ์กฐ โš ๏ธ :

A โ†’ B โ†’ A
A ์˜ ์นด์šดํŠธ = 1 (B ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)
B ์˜ ์นด์šดํŠธ = 1 (A ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)

์™ธ๋ถ€์—์„œ A, B ์‚ฌ์šฉ ์•ˆ ํ•ด๋„
์„œ๋กœ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ•œ ์นด์šดํŠธ 0 ์•ˆ ๋จ
โ†’ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ โŒ

์ฑ„ํƒ ์‚ฌ๋ก€:

  • Python (๋ณด์กฐ GC ์™€ ํ•จ๊ป˜)
  • Objective-C, Swift (ARC)
  • C++ (shared_ptr)
  • โ†’ ์ž๋ฐ”๋Š” ์ฑ„ํƒ X

์•Œ๊ณ ๋ฆฌ์ฆ˜ 2 โ€” Mark-Sweep (1960) โญ

LISP ์–ธ์–ด์˜ John McCarthy ๊ฐ€ 1960๋…„์— ์ œ์•ˆ.

์•„์ด๋””์–ด:

  • GC ์‹œ ๋ชจ๋“  ์‚ด์•„์žˆ๋Š” ๊ฐ์ฒด ๋งˆํ‚น (Mark)
  • ๋งˆํ‚น ์•ˆ ๋œ ๊ฐ์ฒด ๋ชจ๋‘ ํšŒ์ˆ˜ (Sweep)

์žฅ์ :

  • ์ˆœํ™˜ ์ฐธ์กฐ ํ•ด๊ฒฐ (Reachability ๊ธฐ๋ฐ˜)
  • ๋‹จ์ˆœํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜
  • ๋ชจ๋“  GC ์˜ ํ† ๋Œ€

๋‹จ์ :

  • STW ํ•„์š”
  • ๋‹จํŽธํ™” ๋ฐœ์ƒ

๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ฆผ:

Before:
[A][B][C][D][E][F]
Mark: A, C, E ๊ฐ€ Live

After Sweep:
[A][_][C][_][E][_]
   ๋น„์›€    ๋น„์›€    ๋น„์›€
   โ† ๋‹จํŽธํ™”

์•Œ๊ณ ๋ฆฌ์ฆ˜ 3 โ€” Mark-Sweep-Compact

Mark-Sweep ์˜ ๋‹จํŽธํ™”๋ฅผ ํ•ด๊ฒฐ.

์•„์ด๋””์–ด:

  • Mark-Sweep ํ›„ ์••์ถ• (Compact) ๋‹จ๊ณ„ ์ถ”๊ฐ€
  • ์‚ด์•„์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ํ•œ์ชฝ์œผ๋กœ ๋ชจ์Œ

์žฅ์ :

  • ๋‹จํŽธํ™” ํ•ด์†Œ
  • ํฐ ๊ฐ์ฒด ํ• ๋‹น ๊ฐ€๋Šฅ

๋‹จ์ :

  • Compact ๋น„์šฉ (๊ฐ์ฒด ์ด๋™)
  • ์ฐธ์กฐ ์—…๋ฐ์ดํŠธ ํ•„์š”

๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ฆผ:

Sweep ํ›„:
[A][_][C][_][E][_]

Compact ํ›„:
[A][C][E][_][_][_]
       โ† ๋ชจ๋“  ๋นˆ ๊ณต๊ฐ„ ๋’ค๋กœ

์•Œ๊ณ ๋ฆฌ์ฆ˜ 4 โ€” Generational (1980s) โญ

์•ฝํ•œ ์„ธ๋Œ€ ๊ฐ€์„ค (Unit 5.1) ํ™œ์šฉ.

์•„์ด๋””์–ด:

  • Heap์„ Young / Old ๋ถ„๋ฆฌ
  • Young: Copying GC (์ž์ฃผ, ๋น ๋ฆ„)
  • Old: Mark-Sweep-Compact (๊ฐ€๋”, ํฐ ์ •๋ฆฌ)

์žฅ์ :

  • ๋งค์šฐ ํšจ์œจ์ 
  • ์„ธ๋Œ€๋ณ„ ์ตœ์ ํ™”

๋‹จ์ :

  • ๊ตฌ์กฐ ๋ณต์žก
  • Old โ†’ Young ์ฐธ์กฐ ์ถ”์  (Card Table)

์ž๋ฐ”์˜ ์„ ํƒ โ€” Generational โญ

์ž๋ฐ”๋Š” Generational GC ๋ฅผ ๊ธฐ๋ณธ ์ฑ„ํƒ:

์™œ?:
1. ์•ฝํ•œ ์„ธ๋Œ€ ๊ฐ€์„ค ์˜ ํ†ต์ฐฐ ํ™œ์šฉ
2. STW ์งง์Œ (Minor GC)
3. ํฐ ์ •๋ฆฌ๋Š” ๊ฐ€๋”๋งŒ (Major GC)
4. ํ˜„๋Œ€ ๋ชจ๋“  ์ž๋ฐ” GC ๊ฐ€ ์ด ๊ธฐ๋ฐ˜

โ†’ Serial, Parallel, CMS, G1, ZGC ๋ชจ๋‘ Generational + ์ถ”๊ฐ€ ์ตœ์ ํ™”.


ํ•ต์‹ฌ ํ†ต์ฐฐ

"GC ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ง„ํ™” = 'ํšจ์œจ + ์•ˆ์ „' ์˜ ์ถ”๊ตฌ."

Reference Counting์˜ ์ง๊ด€์„ฑ โ†’ ์ˆœํ™˜ ์ฐธ์กฐ ๋ฌธ์ œ ๋ฐœ๊ฒฌ โ†’ Mark-Sweep ์˜ ์•ˆ์ „์„ฑ โ†’ ๋‹จํŽธํ™” ๋ฌธ์ œ โ†’ Mark-Sweep-Compact์˜ ์••์ถ• โ†’ ๋ชจ๋“  ๊ฐ์ฒด ๋˜‘๊ฐ™์ด ๋‹ค๋ฃจ๋Š” ๋น„ํšจ์œจ โ†’ Generational์˜ ํšจ์œจ.

๊ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ด์ „ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ•œ๊ณ„๋ฅผ ํ•ด๊ฒฐ. ์ž๋ฐ”๋Š” ๊ฐ€์žฅ ์ง„ํ™”๋œ ํ˜•ํƒœ์ธ Generational ์ฑ„ํƒ, ์ดํ›„ G1, ZGC ๋“ฑ์œผ๋กœ ๋” ์ง„ํ™”.


๐Ÿ’ฃ 3. ์—†์œผ๋ฉด ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ฐจ์ด๋ฅผ ๋ชจ๋ฅด๋ฉด ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์—์„œ ๋ง‰ํž™๋‹ˆ๋‹ค.

์‹œ๋‚˜๋ฆฌ์˜ค 1: "์™œ ์ž๋ฐ”๋Š” Reference Counting ์•ˆ ์“ฐ๋‚˜?"

๋ฉด์ ‘ ์งˆ๋ฌธ:

"Python ์ฒ˜๋Ÿผ Reference Counting ์“ฐ๋ฉด ์ฆ‰์‹œ ํšŒ์ˆ˜ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š๋‚˜์š”?"

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ๋ฅด๋ฉด:

  • "์Œ... ์ž๋ฐ”๊ฐ€ ๊ทธ๋ƒฅ ๊ทธ๋ ‡๊ฒŒ ๋งŒ๋“ค์—ˆ๋‚˜๋ด์š”"
  • โ†’ ์‹œ๋‹ˆ์–ด ์ž๊ฒฉ ์˜์‹ฌ

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์•Œ๋ฉด:

  • "์ˆœํ™˜ ์ฐธ์กฐ ๋ฌธ์ œ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค."
  • ๊ตฌ์ฒด์  ์˜ˆ์‹œ + ๊ทธ๋ฆผ์œผ๋กœ ์„ค๋ช…
  • "Python ๋„ Reference Counting ๋งŒ์œผ๋ก  ๋ถ€์กฑํ•ด์„œ Cycle Detector ๋ณด์กฐ ์‚ฌ์šฉ"
  • โ†’ ์‹œ๋‹ˆ์–ด ์ธ์‹

์‹œ๋‚˜๋ฆฌ์˜ค 2: ๋‹จํŽธํ™”์˜ ์˜๋ฏธ ์ดํ•ด ๋ชปํ•จ

์šด์˜ ํ™˜๊ฒฝ:

Heap ์‚ฌ์šฉ๋Ÿ‰: 70%
๊ทธ๋Ÿฌ๋‚˜ 1MB ์ด์ƒ ๊ฐ์ฒด ํ• ๋‹น ์‹œ OOM

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ๋ฅด๋ฉด:

  • "Heap 30% ๋‚จ์•˜๋Š”๋ฐ ์™œ OOM?"
  • ์ดํ•ด ๋ถˆ๊ฐ€

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์•Œ๋ฉด:

  • "๋‹จํŽธํ™” ๋•Œ๋ฌธ"
  • "Mark-Sweep ํ›„ ๋นˆ ๊ณต๊ฐ„์ด ์ž‘์€ ์กฐ๊ฐ๋“ค๋กœ ํฉ์–ด์ ธ ์žˆ์Œ"
  • "ํฐ ์—ฐ์† ๊ณต๊ฐ„์ด ๋ถ€์กฑ"
  • โ†’ Compact ๊ฐ€ ์žˆ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ (G1 ๋“ฑ) ์œผ๋กœ ์ „ํ™˜

์‹œ๋‚˜๋ฆฌ์˜ค 3: ILIC ์šด์˜์˜ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ํƒ

์‹ ๊ทœ ILIC ์‹œ์Šคํ…œ ๋ฐฐํฌ:

  • Heap: 8GB
  • ํ‰๊ท  ์‘๋‹ต 100ms
  • ๊ธฐ๋ณธ GC ์‚ฌ์šฉ โ†’ ๊ฐ€๋” 5์ดˆ ๋ฉˆ์ถค

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ๋ฅด๋ฉด:

  • "์ด์ƒํ•˜๋‹ค... ๋ฉ”๋ชจ๋ฆฌ ๋Š˜๋ ค?"
  • ๊ทผ๋ณธ ํ•ด๊ฒฐ X

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์•Œ๋ฉด:

  • "Parallel GC ์˜ Old ์˜์—ญ Full GC ๊ฐ€ ๊ธธ์Œ"
  • "G1 ๋˜๋Š” ZGC ๋กœ ์ „ํ™˜"
  • "G1 = Region ๊ธฐ๋ฐ˜ + ๋ถ€๋ถ„ ์••์ถ•, ZGC = ๊ฑฐ์˜ ๋ฉˆ์ถค ์—†์Œ"

์‹œ๋‚˜๋ฆฌ์˜ค 4: Python ์—์„œ ์ž๋ฐ”๋กœ ์ „ํ™˜

Python ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž๋ฐ” ์‹œ์ž‘:

"GC ๊ฐ€ ์ž์ฃผ ๋ฉˆ์ถฐ์š”. Python ์€ ์•ˆ ๊ทธ๋žฌ๋Š”๋ฐ?"

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ๋ฅด๋ฉด:

  • ์ด์œ  ๋ชป ์ฐพ์Œ

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์•Œ๋ฉด:

  • "Python ์€ Reference Counting ์œ„์ฃผ โ†’ ์ฆ‰์‹œ ํšŒ์ˆ˜"
  • "์ž๋ฐ”๋Š” Generational + Mark-Sweep โ†’ ๊ฐ€๋” STW"
  • "๊ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ trade-off"
  • โ†’ ์ •ํ™•ํ•œ ๋น„๊ต

์‹œ๋‚˜๋ฆฌ์˜ค 5: ๋ฉด์ ‘ ๊นŠ์ด ์งˆ๋ฌธ

"GC ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ง„ํ™”๋ฅผ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”"
"Mark-Sweep ์˜ ๋‹จ์ ์ด ๋ญ”๊ฐ€์š”?"
"์™œ ์ž๋ฐ”๋Š” Mark-Sweep-Compact ์™€ Copying ๋‘˜ ๋‹ค ์“ฐ๋‚˜์š”?"

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ๋ฅด๋ฉด:

  • ๊นŠ์ด ์žˆ๋Š” ๋‹ต ๋ถˆ๊ฐ€

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์•Œ๋ฉด:

  • 4๊ฐ€์ง€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ง„ํ™” + ์žฅ๋‹จ์ 
  • ์ž๋ฐ”์˜ ์ฑ„ํƒ ์ด์œ 
  • โ†’ ์‹œ๋‹ˆ์–ด ๋‹ต๋ณ€

์‹œ๋‚˜๋ฆฌ์˜ค 6: ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ถ„์„

๊ด€์ฐฐ: Heap ์‚ฌ์šฉ๋Ÿ‰ ๊ณ„์† ์ฆ๊ฐ€
GC ํ›„์—๋„ ์ค„์ง€ ์•Š์Œ

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ๋ฅด๋ฉด:

  • "GC ๊ฐ€ ์•ˆ ๋™์ž‘ํ•˜๋‚˜?"

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์•Œ๋ฉด:

  • "GC ๋Š” ๋™์ž‘ํ•˜๋Š”๋ฐ Reachability ๊ฐ€ ์žˆ๋Š” ๊ฐ์ฒด๋Š” ๋ชป ํšŒ์ˆ˜"
  • "์ฐธ์กฐ ๋Š๊น€ ์–ด๋””์„œ ์•ˆ ๋˜๋Š”์ง€ ๋ถ„์„"
  • โ†’ static ์ปฌ๋ ‰์…˜, ThreadLocal ๋“ฑ ์˜์‹ฌ

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ดํ•ด์˜ ์ค‘์š”์„ฑ

์‹œ๋‚˜๋ฆฌ์˜ค์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ๋ฅด๋ฉด์•Œ๊ณ ๋ฆฌ์ฆ˜ ์•Œ๋ฉด
Reference Counting ์งˆ๋ฌธ๋ง‰๋ง‰ํ•จ์ˆœํ™˜ ์ฐธ์กฐ ์„ค๋ช…
๋‹จํŽธํ™” OOM์ดํ•ด XCompact ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ํƒ
์šด์˜ GC ์„ ํƒ๊ธฐ๋ณธ ์‚ฌ์šฉ์ƒํ™ฉ๋ณ„ ์„ ํƒ
์–ธ์–ด ๋น„๊ตํ‘œ๋ฉด์ ๊นŠ์ด ์žˆ๋Š” ๋น„๊ต
๋ฉด์ ‘ ๊นŠ์ด ์งˆ๋ฌธํƒˆ๋ฝ์‹œ๋‹ˆ์–ด ๋‹ต๋ณ€
๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜"GC ๋ฌธ์ œ""์ฐธ์กฐ ๋ฌธ์ œ"

โ†’ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ดํ•ด๋Š” ์‹œ๋‹ˆ์–ด์˜ ์ฐจ๋ณ„ํ™” ์˜์—ญ.


โœ… 4. ํ•ด๊ฒฐ์ฑ… โ€” 4๊ฐ€์ง€ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ •ํ™•ํžˆ

์•Œ๊ณ ๋ฆฌ์ฆ˜ 1: Reference Counting โญ

ํ•ต์‹ฌ ๋™์ž‘

๋ชจ๋“  ๊ฐ์ฒด์— ์ฐธ์กฐ ์นด์šดํŠธ ๋ณด์œ :

๊ฐ์ฒด A:
  - ๋ฐ์ดํ„ฐ
  - ์ฐธ์กฐ ์นด์šดํŠธ: 1

์ฐธ์กฐ ์ถ”๊ฐ€/์ œ๊ฑฐ ์‹œ:

Object x = a;  // a ์˜ ์นด์šดํŠธ +1
x = null;      // a ์˜ ์นด์šดํŠธ -1

์นด์šดํŠธ 0 โ†’ ์ฆ‰์‹œ ํšŒ์ˆ˜.


์žฅ์  โญ

1. ์ฆ‰๊ฐ์  ํšŒ์ˆ˜

  • ์นด์šดํŠธ 0 ๋˜๋Š” ์ˆœ๊ฐ„ ์ฆ‰์‹œ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ
  • ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ 

2. STW ์—†์Œ

  • ๋ณ„๋„ GC ์‚ฌ์ดํด ์—†์Œ
  • ์‚ฌ์šฉ์ž ์‘๋‹ต์— ์˜ํ–ฅ X

3. ๋ถ„์‚ฐ๋œ ์ž‘์—…

  • ๋งค ์ฐธ์กฐ ๋ณ€๊ฒฝ ์‹œ ์กฐ๊ธˆ์”ฉ ์ž‘์—…
  • ํ•œ ๋ฒˆ์— ํฐ ๋ถ€ํ•˜ ์—†์Œ

๋‹จ์  โญโญ (์ค‘์š”)

1. ์ˆœํ™˜ ์ฐธ์กฐ ๋ฌธ์ œ โš ๏ธ (์ž๊ธฐ ์ ๊ฒ€ Q1)

class Node {
    Node next;
}

Node a = new Node();
Node b = new Node();

a.next = b;  // a โ†’ b
b.next = a;  // b โ†’ a (์ˆœํ™˜!)

a = null;  // a ์˜ ์™ธ๋ถ€ ์ฐธ์กฐ ๋Š์Œ
b = null;  // b ์˜ ์™ธ๋ถ€ ์ฐธ์กฐ ๋Š์Œ

// ๊ทธ๋Ÿฌ๋‚˜:
// a ์˜ ์นด์šดํŠธ: 1 (b.next ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)
// b ์˜ ์นด์šดํŠธ: 1 (a.next ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)
// โ†’ ์นด์šดํŠธ 0 ์•ˆ ๋จ โ†’ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ โŒ

๊ทธ๋ฆผ:

[Stack] (์™ธ๋ถ€ ์ฐธ์กฐ ์—†์Œ)

[Heap]
  Node A โ”€โ†’ Node B
       โ†‘      โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
       
A ์˜ ์นด์šดํŠธ: 1 (B ์˜ next)
B ์˜ ์นด์šดํŠธ: 1 (A ์˜ next)
โ†’ ๋‘˜ ๋‹ค ํšŒ์ˆ˜ X

2. ์นด์šดํŠธ ๊ด€๋ฆฌ ๋น„์šฉ

  • ๋งค ์ฐธ์กฐ ๋ณ€๊ฒฝ๋งˆ๋‹ค +1 / -1
  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋™๊ธฐํ™” ํ•„์š”

3. ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ

  • ๋ชจ๋“  ๊ฐ์ฒด์— ์นด์šดํŠธ ํ•„๋“œ ์ถ”๊ฐ€
  • 8 byte ๊ฐ์ฒด์— 4 byte ์นด์šดํŠธ?

์ฑ„ํƒ ์–ธ์–ด

์–ธ์–ด์‚ฌ์šฉ
PythonReference Counting + Cycle Detector (๋ณด์กฐ)
Objective-CARC (Automatic Reference Counting)
SwiftARC
C++shared_ptr
JavaโŒ ์‚ฌ์šฉ ์•ˆ ํ•จ

์•Œ๊ณ ๋ฆฌ์ฆ˜ 2: Mark-and-Sweep โญ

ํ•ต์‹ฌ ๋™์ž‘

2๋‹จ๊ณ„:

Mark ๋‹จ๊ณ„:

  • GC Root ๋ถ€ํ„ฐ ์‹œ์ž‘
  • ๋„๋‹ฌ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด ๋ชจ๋‘ ๋งˆํ‚น

Sweep ๋‹จ๊ณ„:

  • ๋งˆํ‚น ์•ˆ ๋œ ๊ฐ์ฒด ๋ชจ๋‘ ํšŒ์ˆ˜
[Stack]
  ref1, ref2

[Heap]
  Object A โ†โ”€โ”€โ”€ ref1     (Mark)
  Object B               (X)
  Object C โ†โ”€โ”€โ”€ ref2     (Mark)
  Object D โ†โ”€ A          (Mark)
  Object E               (X)

๋™์ž‘ ๊ทธ๋ฆผ

Step 1: Initial

[Heap]
  A B C D E F G H
  โ†‘   โ†‘       โ†‘
  GC Root ๋“ค

Step 2: Mark

[Heap]
  A* B C* D E F* G H
  *=๋งˆํ‚น๋จ (Live)
  
GC Root ์—์„œ ๋„๋‹ฌ ๊ฐ€๋Šฅ: A, C, F

Step 3: Sweep

[Heap]
  A _ C _ _ F _ _
       (B,D,E,G,H ํšŒ์ˆ˜)

์žฅ์  โญ

1. ์ˆœํ™˜ ์ฐธ์กฐ ํ•ด๊ฒฐ

  • Reachability ๊ธฐ๋ฐ˜ โ†’ ์ˆœํ™˜์€ ์™ธ๋ถ€ ์ฐธ์กฐ ์—†์œผ๋ฉด ํšŒ์ˆ˜๋จ
  • Reference Counting ์˜ ๊ฐ€์žฅ ํฐ ๋‹จ์  ํ•ด๊ฒฐ

2. ๋‹จ์ˆœํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ์‰ฌ์šด ๊ตฌํ˜„
  • ๋ชจ๋“  GC ์˜ ํ† ๋Œ€

๋‹จ์  โญ

1. STW ํ•„์š”

  • ๋งˆํ‚น ์ค‘ ๊ฐ์ฒด ๋ณ€๊ฒฝ X
  • ๋ชจ๋“  Application Thread ์ •์ง€

2. ๋‹จํŽธํ™” ๋ฐœ์ƒ โš ๏ธ

  • Sweep ํ›„ ๋นˆ ๊ณต๊ฐ„์ด ๊ณณ๊ณณ์—
  • ํฐ ๊ฐ์ฒด ํ• ๋‹น ์–ด๋ ค์›€
After Sweep:
[A][_][C][_][_][F][_][_]

โ†’ 8 byte ๋นˆ ๊ณต๊ฐ„ 5๊ฐœ
โ†’ ๊ทธ๋Ÿฌ๋‚˜ 16 byte ๊ฐ์ฒด ํ• ๋‹น ๋ถˆ๊ฐ€ (์—ฐ์† ๊ณต๊ฐ„ ์—†์Œ)

3. Mark ์‹œ๊ฐ„ ๋น„๋ก€

  • ๊ฐ์ฒด ์ˆ˜ ๋งŽ์„์ˆ˜๋ก Mark ์‹œ๊ฐ„ ์ฆ๊ฐ€

์ž๋ฐ”์—์„œ์˜ ์‚ฌ์šฉ

์ž๋ฐ”์˜ GC ๋Š” Mark-Sweep ์˜ ๋ณ€ํ˜•:

  • Old Generation ์˜ GC ์— ์‚ฌ์šฉ
  • Compact ๊ฐ€ ์ถ”๊ฐ€๋œ ํ˜•ํƒœ (Mark-Sweep-Compact)

์•Œ๊ณ ๋ฆฌ์ฆ˜ 3: Mark-Sweep-Compact โญ

ํ•ต์‹ฌ ๋™์ž‘

3๋‹จ๊ณ„:

  1. Mark: ์‚ด์•„์žˆ๋Š” ๊ฐ์ฒด ๋งˆํ‚น
  2. Sweep: ์ฃฝ์€ ๊ฐ์ฒด ํšŒ์ˆ˜
  3. Compact: ์‚ด์•„์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ํ•œ์ชฝ์œผ๋กœ ์••์ถ•

๋™์ž‘ ๊ทธ๋ฆผ

Step 1-2: Mark + Sweep (๊ฐ™์Œ)

After Sweep:
[A][_][C][_][_][F][_][_]

Step 3: Compact

After Compact:
[A][C][F][_][_][_][_][_]
       (์‚ด์•„์žˆ๋Š” ๊ฒƒ ์•ž์ชฝ ๋ชจ์Œ)
       (๋นˆ ๊ณต๊ฐ„ ๋’ค๋กœ)

์žฅ์  โญ

1. ๋‹จํŽธํ™” ํ•ด์†Œ

  • ๋นˆ ๊ณต๊ฐ„์ด ํ•œ๊ณณ์— ๋ชจ์ž„
  • ํฐ ๊ฐ์ฒด๋„ ํ• ๋‹น ๊ฐ€๋Šฅ

2. ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ

  • ์‚ฌ์šฉ ์ค‘ ์˜์—ญ ์ถ•์†Œ

๋‹จ์  โญ

1. Compact ๋น„์šฉ

  • ๊ฐ์ฒด ์ด๋™ ๋น„์šฉ
  • ๋ชจ๋“  ์ฐธ์กฐ ์—…๋ฐ์ดํŠธ ํ•„์š”

2. STW ๊ธธ์–ด์ง

  • Mark + Sweep + Compact = ๋” ๊ธด STW

์ž๋ฐ”์—์„œ์˜ ์‚ฌ์šฉ

Old Generation ์—์„œ ์‚ฌ์šฉ:

  • Old GC = Mark-Sweep-Compact (์ „ํ†ต)
  • G1 GC ๋„ Old ์˜์—ญ์— ๋ถ€๋ถ„ ์ ์šฉ

์•Œ๊ณ ๋ฆฌ์ฆ˜ 4: Generational โญโญโญ (์ž๋ฐ”์˜ ์‹ค์ œ)

ํ•ต์‹ฌ ๋™์ž‘

์•ฝํ•œ ์„ธ๋Œ€ ๊ฐ€์„ค ํ™œ์šฉ:

  • Young ์˜์—ญ (Eden + Survivor)
  • Old ์˜์—ญ
  • ๊ฐ์ž ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜

Young ์˜์—ญ: Copying GC

  • Eden + From โ†’ To ๋กœ ๋ณต์‚ฌ
  • ์ž๋™ ์••์ถ•
  • ๋งค์šฐ ๋น ๋ฆ„

Old ์˜์—ญ: Mark-Sweep-Compact

  • ๊ฐ€๋” ๋ฐœ์ƒ
  • STW ๊ธธ์ง€๋งŒ ์ž์ฃผ X

Copying GC ์˜ ๋™์ž‘ (Young ์˜์—ญ)

Before Minor GC:
[Eden + From]
  A B C D E (B, D ๋Š” Garbage)

[To]
  ๋น„์–ด์žˆ์Œ

Copying:
  ์‚ด์•„์žˆ๋Š” A, C, E ๋ฅผ To ๋กœ ๋ณต์‚ฌ

After:
[Eden + From]
  ๋น„์›€

[To]
  A C E

ํšจ๊ณผ:

  • ์ž๋™ ์••์ถ•
  • ๋‹จํŽธํ™” X
  • ๋น ๋ฆ„ (์‚ด์•„์žˆ๋Š” ๊ฒƒ ์ ์Œ)

์žฅ์  โญ

1. ๋งค์šฐ ํšจ์œจ์ 

  • ์•ฝํ•œ ์„ธ๋Œ€ ๊ฐ€์„ค ํ™œ์šฉ
  • Young ์ž์ฃผ GC, ๋น ๋ฆ„
  • Old ๊ฐ€๋” GC, ํผ

2. ๋‹จํŽธํ™” ํ•ด์†Œ

  • Young: Copying ์œผ๋กœ ์ž๋™
  • Old: Compact

3. ์งง์€ STW (๋ณดํ†ต)

  • Minor GC: ~10ms
  • Major GC: ๊ฐ€๋”๋งŒ

๋‹จ์  โญ

1. ๊ตฌ์กฐ ๋ณต์žก

  • Eden + Survivor 0/1 + Old
  • Promotion ๋กœ์ง
  • Card Table ํ•„์š”

2. ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ

  • Survivor ์˜์—ญ (์‹ค์ œ ์‚ฌ์šฉ์€ ์ ˆ๋ฐ˜)
  • Card Table ์ž์ฒด

์ž๋ฐ”์˜ ์ฑ„ํƒ โญ

์ž๋ฐ” ๋ชจ๋“  GC ์˜ ๊ธฐ๋ฐ˜:

  • Serial GC (๊ฐ€์žฅ ๋‹จ์ˆœ)
  • Parallel GC (๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ)
  • CMS (Concurrent)
  • G1 (Region)
  • ZGC (์ €์ง€์—ฐ)

โ†’ ๋ชจ๋‘ Generational + ์ถ”๊ฐ€ ์ตœ์ ํ™”.


4๊ฐ€์ง€ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋น„๊ต ํ‘œ โญโญ (๋ฉด์ ‘ ๋‹ต๋ณ€ ํ•ต์‹ฌ)

Reference CountingMark-SweepMark-Sweep-CompactGenerational
์ˆœํ™˜ ์ฐธ์กฐโŒ ๋ˆ„์ˆ˜โœ… ํ•ด๊ฒฐโœ… ํ•ด๊ฒฐโœ… ํ•ด๊ฒฐ
STW์—†์Œ๊น€๋งค์šฐ ๊น€์งง์Œ (Minor)
๋‹จํŽธํ™”์—†์Œ์žˆ์Œ์—†์Œ (์••์ถ•)์—†์Œ (Young ์ž๋™)
์ฆ‰์‹œ ํšŒ์ˆ˜โœ…XXX
๊ตฌ์กฐ๋‹จ์ˆœ๋‹จ์ˆœ๋ณดํ†ต๋ณต์žก
์ž๋ฐ” ์ฑ„ํƒโŒโ–ณ (๋ณ€ํ˜•)โ–ณ (Old ์˜์—ญ)โœ…

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ง„ํ™”์˜ ํ๋ฆ„

1. Reference Counting (1950s)
   โ†“ ์ˆœํ™˜ ์ฐธ์กฐ ๋ฌธ์ œ ๋ฐœ๊ฒฌ
   
2. Mark-Sweep (1960s)
   โ†“ ๋‹จํŽธํ™” ๋ฌธ์ œ ๋ฐœ๊ฒฌ
   
3. Mark-Sweep-Compact (1970s)
   โ†“ ๋ชจ๋“  ๊ฐ์ฒด ๊ฐ™๊ฒŒ ๋‹ค๋ฃจ๋Š” ๋น„ํšจ์œจ
   
4. Generational (1980s) โญ
   โ†“ ์ž๋ฐ” ์ฑ„ํƒ (1995)
   โ†“ ๋” ๋ฐœ์ „
   
5. G1, ZGC, Shenandoah (2010s+)
   โ†“ Region ๊ธฐ๋ฐ˜, Concurrent

โ†’ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ง„ํ™” = GC ์ง„ํ™”.


๐Ÿ—๏ธ 5. ๋‚ด๋ถ€ ๋™์ž‘ ์›๋ฆฌ

Reference Counting ์˜ ์ž์„ธํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜

# Python ์˜ˆ์‹œ (์ž๋ฐ” ์•„๋‹˜, ์ดํ•ด์šฉ)
a = SomeObject()  # a ์˜ ์นด์šดํŠธ: 1
b = a              # ์นด์šดํŠธ: 2
a = None           # ์นด์šดํŠธ: 1
b = None           # ์นด์šดํŠธ: 0 โ†’ ์ฆ‰์‹œ ํšŒ์ˆ˜

JVM ์ด๋ผ๋ฉด (๊ฐ€์ƒ):

// ์˜์‚ฌ ์ฝ”๋“œ โ€” ์ž๋ฐ”๋Š” ์ด๋ ‡๊ฒŒ ์•ˆ ํ•จ
class Object {
    int referenceCount;
    
    void onReferenceAdded() { referenceCount++; }
    void onReferenceRemoved() {
        referenceCount--;
        if (referenceCount == 0) {
            free(this);  // ์ฆ‰์‹œ ํ•ด์ œ
        }
    }
}

๋ชจ๋“  ์ฐธ์กฐ ๋ณ€๊ฒฝ ์‹œ ์นด์šดํŠธ ๊ฐฑ์‹  โ€” ๋น„์šฉ ๋†’์Œ.


์ˆœํ™˜ ์ฐธ์กฐ์˜ ์ •ํ™•ํ•œ ๋ฌธ์ œ

class Person {
    Person friend;  // ์นœ๊ตฌ ์ฐธ์กฐ
}

// ์‹œ๋‚˜๋ฆฌ์˜ค
Person alice = new Person();   // alice: cnt=1 (์™ธ๋ถ€ ๋ณ€์ˆ˜)
Person bob = new Person();     // bob: cnt=1

alice.friend = bob;  // bob: cnt=2
bob.friend = alice;  // alice: cnt=2

alice = null;  // alice ๊ฐ์ฒด: cnt=1 (bob.friend ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)
bob = null;    // bob ๊ฐ์ฒด: cnt=1 (alice.friend ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)

// ์™ธ๋ถ€ ์ฐธ์กฐ ๋ชจ๋‘ ๋Š๊ฒผ๋Š”๋ฐ
// ์„œ๋กœ 1์”ฉ ์นด์šดํŠธ โ†’ ์˜์›ํžˆ ํšŒ์ˆ˜ X

์‹œ๊ฐํ™”:

[Stack] (๋น„์–ด์žˆ์Œ โ€” ์™ธ๋ถ€ ์ฐธ์กฐ X)

[Heap]
  alice ๊ฐ์ฒด (cnt=1) โ”€โ”€โ†’ bob ๊ฐ์ฒด (cnt=1)
       โ†‘                    โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
       (cycle)

โ†’ ๋ˆ„์ˆ˜.

Mark-Sweep ์ด๋ผ๋ฉด ํ•ด๊ฒฐ:

GC Root: ์™ธ๋ถ€ ์ฐธ์กฐ ์—†์Œ
โ†’ Reachability: alice, bob ๋‘˜ ๋‹ค ๋„๋‹ฌ ๋ถˆ๊ฐ€
โ†’ Sweep ์‹œ ํšŒ์ˆ˜

Mark ์˜ ์ž์„ธํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜

DFS (Depth-First Search) ์‚ฌ์šฉ:

1. GC Root ๋“ค์„ work-list ์— ์ถ”๊ฐ€
2. while work-list ๋น„์–ด์žˆ์ง€ ์•Š์Œ:
   a. ๊ฐ์ฒด ํ•˜๋‚˜ ๊บผ๋ƒ„
   b. ๋งˆํ‚น
   c. ๊ทธ ๊ฐ์ฒด์˜ ๋ชจ๋“  ์ฐธ์กฐ๋ฅผ work-list ์— ์ถ”๊ฐ€
3. ๋๋‚˜๋ฉด ๋งˆํ‚น ์•ˆ ๋œ ๊ฒƒ์ด Garbage

์‹œ๊ฐ„ ๋ณต์žก๋„:

  • ๊ฐ์ฒด ์ˆ˜ N
  • ์ฐธ์กฐ ์ˆ˜ E
  • O(N + E)

Sweep ์˜ ์ž์„ธํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜

for each ๊ฐ์ฒด in Heap:
    if ๋งˆํ‚น ์•ˆ ๋จ:
        free(๊ฐ์ฒด)
    else:
        clear_mark(๊ฐ์ฒด)  // ๋‹ค์Œ GC ์œ„ํ•ด

Free List:

  • ํšŒ์ˆ˜๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ถ”์ 
  • ๋‹ค์Œ ํ• ๋‹น ์‹œ ์‚ฌ์šฉ

Compact ์˜ ์ž์„ธํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜

๊ฐ์ฒด ์ด๋™ + ์ฐธ์กฐ ์—…๋ฐ์ดํŠธ:

Step 1: ์ƒˆ ์œ„์น˜ ๊ณ„์‚ฐ
  A: 0x1000 โ†’ 0x1000 (๊ทธ๋Œ€๋กœ)
  C: 0x2000 โ†’ 0x1100 (์•ž์œผ๋กœ ์ด๋™)
  F: 0x3000 โ†’ 0x1200 (์•ž์œผ๋กœ ์ด๋™)

Step 2: ๊ฐ์ฒด ๋ณต์‚ฌ
  C ์˜ ๋ฐ์ดํ„ฐ โ†’ 0x1100
  F ์˜ ๋ฐ์ดํ„ฐ โ†’ 0x1200

Step 3: ๋ชจ๋“  ์ฐธ์กฐ ์—…๋ฐ์ดํŠธ
  A ๊ฐ€ C ๋ฅผ ์ฐธ์กฐ โ†’ 0x2000 โ†’ 0x1100
  ์™ธ๋ถ€์—์„œ F ์ฐธ์กฐ โ†’ 0x3000 โ†’ 0x1200

๋น„์šฉ:

  • ๊ฐ์ฒด ๋ณต์‚ฌ
  • ์ฐธ์กฐ ์ถ”์  + ์—…๋ฐ์ดํŠธ
  • โ†’ STW ๊ธธ์–ด์ง

Copying GC ์˜ ํšจ์œจ์„ฑ

Young ์˜์—ญ์—์„œ ์‚ฌ์šฉ:

Eden + From: [A][B][C][D][E]
              โ†“ Live: A, C, E

To: ๋น„์–ด์žˆ์Œ
              โ†“ Copying

To: [A][C][E]
Eden + From: ํ†ต์งธ๋กœ ๋น„์›€

์™œ ๋น ๋ฅธ๊ฐ€:
1. ์‚ด์•„์žˆ๋Š” ๊ฐ์ฒด๋งŒ ๋ณต์‚ฌ (๋ณดํ†ต ์ ์Œ)
2. ๋นˆ ๊ณต๊ฐ„ ํ†ต์งธ๋กœ ๋น„์›€ (free ํ˜ธ์ถœ ์—†์Œ)
3. ์ž๋™ ์••์ถ• (๋ณ„๋„ ๋‹จ๊ณ„ X)

์‹œ๊ฐ„: O(Live ๊ฐ์ฒด ์ˆ˜)


Generational ์˜ ํ†ตํ•ฉ ํ๋ฆ„

์ƒˆ ๊ฐ์ฒด ์ƒ์„ฑ:
  โ†’ Eden ํ• ๋‹น

Eden ๊ฐ€๋“:
  โ†’ Minor GC (Copying)
  โ†’ Eden + From โ†’ To
  โ†’ ์‚ด์•„๋‚จ์€ ๊ฐ์ฒด age +1

Survivor ๊ฐ€๋“ ๋˜๋Š” age = 15:
  โ†’ Promotion (Old ๋กœ ์ด๋™)

Old ๊ฐ€๋“:
  โ†’ Major GC (Mark-Sweep-Compact)
  โ†’ ๋˜๋Š” G1 ์˜ Mixed GC

Old + Metaspace ๊ฐ€๋“:
  โ†’ Full GC (์ „์ฒด)

Card Table ์˜ ํ•„์š”์„ฑ โญ

๋ฌธ์ œ: Old โ†’ Young ์ฐธ์กฐ

@Service
public class FareCache {  // Old ์— ์‚ด์•„์žˆ์Œ
    private List<Fare> recent = new ArrayList<>();  // Young ์— ์žˆ์„ ์ˆ˜ ์žˆ์Œ
}

Minor GC ์‹œ Eden + From ๋งŒ ๋ณด๋ฉด, Old ์˜ cache ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” Young ๊ฐ์ฒด ๋ฅผ Live ๋กœ ์ธ์‹ ๋ชป ํ•จ.

ํ•ด๊ฒฐ โ€” Card Table โญ :

[Old]
  Region 0: [Card 0][Card 1][Card 2][Card 3]
                       โ†“
                       dirty (Young ์ฐธ์กฐ ์žˆ์Œ)

Minor GC:
1. GC Root ์Šค์บ”
2. dirty ์นด๋“œ๋งŒ ์ถ”๊ฐ€ ์Šค์บ”
3. ๋งˆํ‚น

Write Barrier:

  • Old โ†’ Young ์ฐธ์กฐ ๋ฐœ์ƒ ์‹œ ์ž๋™ dirty ๋งˆํ‚น
  • JVM ์ด ์ปดํŒŒ์ผ๋Ÿฌ ์ˆ˜์ค€์—์„œ ์ž๋™ ์‚ฝ์ž…
// ์‚ฌ์šฉ์ž ์ฝ”๋“œ
oldObject.youngRef = youngObject;

// JVM ๋‚ด๋ถ€ (์‹ค์ œ ๋ฐ”์ดํŠธ์ฝ”๋“œ)
oldObject.youngRef = youngObject;
markCardAsDirty(oldObject);  // โ† Write Barrier

โ†’ Generational GC ์˜ ํ•ต์‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜.


๐Ÿ’ป 6. ์‹ค์ „ ์ฝ”๋“œ ์˜ˆ์‹œ

์˜ˆ์‹œ 1: ์ˆœํ™˜ ์ฐธ์กฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ (์ž๋ฐ”์—์„œ๋Š” ์•ˆ์ „)

class Person {
    String name;
    Person friend;
    
    Person(String name) {
        this.name = name;
    }
}

public class CycleDemo {
    public static void main(String[] args) {
        Person alice = new Person("Alice");
        Person bob = new Person("Bob");
        
        alice.friend = bob;
        bob.friend = alice;
        
        // ์™ธ๋ถ€ ์ฐธ์กฐ ๋Š์Œ
        alice = null;
        bob = null;
        
        // GC ๋ฐœ์ƒ ์‹œ โ€” Mark-Sweep ์ด๋ฏ€๋กœ ๋‘˜ ๋‹ค ํšŒ์ˆ˜ โœ…
        // (Reference Counting ์ด์—ˆ๋‹ค๋ฉด ๋ˆ„์ˆ˜)
        
        System.gc();
    }
}

โ†’ ์ž๋ฐ” = Mark-Sweep ๊ธฐ๋ฐ˜ โ†’ ์ˆœํ™˜ ์ฐธ์กฐ ์•ˆ์ „.


์˜ˆ์‹œ 2: ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ โ€” ์˜์™ธ์˜ ํŒจํ„ด

// โŒ ์ž๋ฐ”์—์„œ ์‹ค์ œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ํŒจํ„ด
public class CacheDemo {
    private static final List<Customer> cache = new ArrayList<>();
    
    public static void addCustomer(Customer c) {
        cache.add(c);
        // cache ๋Š” static โ†’ GC Root
        // cache ๊ฐ€ c ๋ฅผ ์ฐธ์กฐ โ†’ c ์˜์›ํžˆ Live
        // โ†’ ๋ˆ„์ˆ˜
    }
}

โ†’ ์ž๋ฐ”๋„ ์ฐธ์กฐ๊ฐ€ ์‚ด์•„์žˆ์œผ๋ฉด GC ๋ชป ํ•จ. Mark-Sweep ์ด๋ผ๋„.


์˜ˆ์‹œ 3: GC ์•Œ๊ณ ๋ฆฌ์ฆ˜๋ณ„ ์‹œ๊ฐํ™”

public class GCVisualizer {
    
    // ์‹œ๋‚˜๋ฆฌ์˜ค: 100๊ฐœ ๊ฐ์ฒด ์ƒ์„ฑ, ์ ˆ๋ฐ˜์€ ์‚ด๋ฆฌ๊ธฐ
    public static void main(String[] args) {
        List<byte[]> survivors = new ArrayList<>();
        
        for (int i = 0; i < 100; i++) {
            byte[] data = new byte[1024 * 100];  // 100KB
            
            if (i % 2 == 0) {
                survivors.add(data);  // ์ ˆ๋ฐ˜๋งŒ ์‚ด๋ฆผ
            }
            // ๋‚˜๋จธ์ง€๋Š” ๋ฉ”์„œ๋“œ ์ข…๋ฃŒ ์‹œ Garbage
        }
        
        System.out.println("์‹ค์ œ ์‚ด์•„์žˆ๋Š” ๊ฐ์ฒด: 50");
        System.out.println("์ด ์ƒ์„ฑ ๊ฐ์ฒด: 100");
        // โ†’ 50 ํšŒ์ˆ˜ ํ•„์š”
        
        System.gc();
        System.out.println("GC ํ›„ โ†’ 50 ํšŒ์ˆ˜๋จ");
    }
}

์•Œ๊ณ ๋ฆฌ์ฆ˜๋ณ„ ๋™์ž‘:

  • Reference Counting: ์ฆ‰์‹œ 50 ํšŒ์ˆ˜ (์ฐธ์กฐ ์—†์–ด์ง„ ์ˆœ๊ฐ„)
  • Mark-Sweep: GC ์‹œ 50 ๋งˆํ‚น + 50 sweep
  • Mark-Sweep-Compact: Sweep + 50 ์‚ด์•„์žˆ๋Š” ๊ฒƒ ์••์ถ•
  • Generational: Eden ์˜ 100๊ฐœ โ†’ Minor GC โ†’ 50 ๋งŒ Survivor ๋กœ

์˜ˆ์‹œ 4: ILIC ์˜ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ํƒ

// ILIC ์šด์˜ ํ™˜๊ฒฝ โ€” JVM ์˜ต์…˜
// -XX:+UseSerialGC      // Serial (๋‹จ์ผ ์Šค๋ ˆ๋“œ)
// -XX:+UseParallelGC    // Parallel (๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ)
// -XX:+UseG1GC          // G1 (Region ๊ธฐ๋ฐ˜) โ€” Java 9+ ๊ธฐ๋ณธ
// -XX:+UseZGC           // ZGC (์ €์ง€์—ฐ)

// ๊ถŒ์žฅ:
java -XX:+UseG1GC \
     -Xms2g -Xmx2g \
     -XX:MaxGCPauseMillis=200 \
     -Xlog:gc*:file=gc.log \
     -jar ilic.jar

์„ ํƒ ๊ธฐ์ค€:

  • ์ž‘์€ Heap, ๋‹จ์ผ CPU: Serial
  • ์ฒ˜๋ฆฌ๋Ÿ‰ ์šฐ์„  (๋ฐฐ์น˜): Parallel
  • ์ผ๋ฐ˜ ๋ฐฑ์—”๋“œ: G1
  • ์ €์ง€์—ฐ ํ•„์ˆ˜ (๋Œ€์šฉ๋Ÿ‰): ZGC

์˜ˆ์‹œ 5: GC ๋กœ๊ทธ์—์„œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ™•์ธ

java -XX:+PrintCommandLineFlags -version

์ถœ๋ ฅ ์˜ˆ์‹œ:

-XX:InitialHeapSize=...
-XX:+UseG1GC                โ† ์‚ฌ์šฉ ์ค‘์ธ GC
-XX:+UseCompressedClassPointers
...

๋˜๋Š”:

java -Xlog:gc*:stdout YourApp

GC ๋กœ๊ทธ์—์„œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ด๋ฆ„ ํ™•์ธ ๊ฐ€๋Šฅ.


์˜ˆ์‹œ 6: ๋‹จํŽธํ™” ์‹คํ—˜

public class FragmentationDemo {
    public static void main(String[] args) {
        List<byte[]> arrays = new ArrayList<>();
        
        // 100๊ฐœ ์ž‘์€ ๋ฐฐ์—ด ํ• ๋‹น
        for (int i = 0; i < 100; i++) {
            arrays.add(new byte[1024 * 100]);  // 100KB
        }
        
        // ์ง์ˆ˜ ์ธ๋ฑ์Šค๋งŒ ์‚ด๋ฆผ (ํ™€์ˆ˜๋Š” Garbage ๋Œ€์ƒ)
        for (int i = 1; i < 100; i += 2) {
            arrays.set(i, null);
        }
        
        System.gc();  // GC ๋ฐœ์ƒ
        
        // Mark-Sweep ๋งŒ ํ–ˆ๋‹ค๋ฉด:
        // ์‚ด์•„์žˆ๋Š” ๊ฒƒ: [A][_][C][_][E][_][G][_]...
        // โ†’ ๋‹จํŽธํ™” โš ๏ธ
        
        // Mark-Sweep-Compact ํ›„:
        // [A][C][E][G][_][_][_][_][_]...
        // โ†’ ์••์ถ• โœ…
        
        // ํฐ ๊ฐ์ฒด ํ• ๋‹น ์‹œ๋„
        try {
            byte[] huge = new byte[1024 * 1024 * 50];  // 50MB
            // Mark-Sweep ๋งŒ์ด๋ผ๋ฉด OOM ๊ฐ€๋Šฅ
            // Compact ํ›„๋ผ๋ฉด OK
        } catch (OutOfMemoryError e) {
            System.out.println("๋‹จํŽธํ™”๋กœ OOM!");
        }
    }
}

โ†’ ์ž๋ฐ”๋Š” Compact ๊ฐ€ ์žˆ์–ด ์•ˆ์ „. C/C++ ๋“ฑ์—์„œ๋Š” ๋‹จํŽธํ™” ์œ„ํ—˜.


์˜ˆ์‹œ 7: ILIC ์˜ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜๋ณ„ ์„ฑ๋Šฅ ๋น„๊ต

# Parallel GC (Java 8 ๊ธฐ๋ณธ)
java -XX:+UseParallelGC -Xmx2g -jar ilic.jar
# ๊ฒฐ๊ณผ: Throughput ๋†’์Œ, Full GC ์‹œ STW 1์ดˆ

# G1 GC (Java 9+ ๊ธฐ๋ณธ)
java -XX:+UseG1GC -Xmx2g -jar ilic.jar
# ๊ฒฐ๊ณผ: Throughput ์•ฝ๊ฐ„ ๋‚ฎ์Œ, STW ~200ms

# ZGC (Java 11+)
java -XX:+UseZGC -Xmx2g -jar ilic.jar
# ๊ฒฐ๊ณผ: Throughput ์•ฝ๊ฐ„ ๋” ๋‚ฎ์Œ, STW ~10ms

์„ ํƒ ๊ธฐ์ค€:

  • API ์‘๋‹ต ์•ˆ์ •์„ฑ โ†’ G1 ๋˜๋Š” ZGC
  • ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ โ†’ Parallel
  • ์‚ฌ์šฉ์ž ์‘๋‹ต ์šฐ์„  โ†’ ZGC

โš ๏ธ 7. ์ฃผ์˜์‚ฌํ•ญ & ํ”ํ•œ ์‹ค์ˆ˜

์‹ค์ˆ˜ 1: "์ž๋ฐ”๋„ Reference Counting ์“ด๋‹ค"

Q: "์ž๋ฐ” GC ์•Œ๊ณ ๋ฆฌ์ฆ˜?"
A: "Reference Counting ๊ฐ™์€ ๊ฑฐ?" โŒ

์ •๋‹ต: ์ž๋ฐ”๋Š” Generational + Mark-Sweep-Compact ์‚ฌ์šฉ. Reference Counting ์‚ฌ์šฉ ์•ˆ ํ•จ.


์‹ค์ˆ˜ 2: ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์ž๋ฐ”์—์„œ ๋ˆ„์ˆ˜๋ผ๊ณ  ์ƒ๊ฐ

"์ˆœํ™˜ ์ฐธ์กฐ ๋งŒ๋“ค๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋„ค!"

์ง„์‹ค: ์ž๋ฐ”๋Š” Mark-Sweep ๊ธฐ๋ฐ˜์ด๋ผ ์ˆœํ™˜ ์ฐธ์กฐ ์•ˆ์ „.

// ์ž๋ฐ”์—์„œ๋Š” OK
a.friend = b;
b.friend = a;
a = null;
b = null;
// โ†’ GC ์‹œ ๋‘˜ ๋‹ค ํšŒ์ˆ˜

์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ๋ˆ„์ˆ˜์ธ ๊ฒฝ์šฐ๋Š” ์™ธ๋ถ€์—์„œ๋„ ์ฐธ์กฐ ํ•  ๋•Œ:

static List<Person> all = new ArrayList<>();
all.add(alice);
all.add(bob);
// โ†’ all ์ด ์‚ด์•„์žˆ์–ด ๋‘˜ ๋‹ค ๋ˆ„์ˆ˜

์‹ค์ˆ˜ 3: Mark-Sweep ๋งŒ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐ

"์ž๋ฐ”๋Š” Mark-Sweep ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค"

์ •๋‹ต: Generational + Mark-Sweep-Compact (Old) + Copying (Young).

๊ฐ ์˜์—ญ๋งˆ๋‹ค ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜.


์‹ค์ˆ˜ 4: STW ๊ฐ€ ํ•ญ์ƒ ๊ธธ๋‹ค๊ณ  ์ƒ๊ฐ

"GC ๋™์•ˆ ํ•ญ์ƒ 1์ดˆ์”ฉ ๋ฉˆ์ถฐ์š”"

์ •๋‹ต:

  • Minor GC: ~10ms
  • Major GC: ~100~500ms
  • Full GC: ~์ˆ˜ ์ดˆ

GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ + Heap ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋‹ค๋ฆ„. ZGC ๋ฉด ms ๋‹จ์œ„.


์‹ค์ˆ˜ 5: Compact ๊ฐ€ ๋ชจ๋“  GC ์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ

Q: "Mark-Sweep ๋‹จํŽธํ™”๋Š”?"
A: "Compact ์žˆ์–ด์„œ OK ์•„๋‹Œ๊ฐ€์š”?" โŒ

์ •๋‹ต: ์ˆœ์ˆ˜ Mark-Sweep ์€ Compact ์—†์Œ. ๋‹จํŽธํ™” ๋ฐœ์ƒ.

์ž๋ฐ”์˜ Old GC ๋Š” Mark-Sweep-Compact (์••์ถ• ์ถ”๊ฐ€).


์‹ค์ˆ˜ 6: GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌด์‹œ = ์šด์˜ ์‚ฌ๊ณ 

java -jar myapp.jar  # ๊ธฐ๋ณธ GC ์‚ฌ์šฉ

๋ฌธ์ œ:

  • Java 8 ๊ธฐ๋ณธ: Parallel (์ฒ˜๋ฆฌ๋Ÿ‰ ์šฐ์„ , ์‘๋‹ต์„ฑ X)
  • Java 9+ ๊ธฐ๋ณธ: G1 (๊ท ํ˜•)

์ƒํ™ฉ๋ณ„ ๊ถŒ์žฅ:

  • ์ž‘์€ Heap (~4GB): G1 ๋˜๋Š” Parallel
  • ํฐ Heap (4~32GB): G1
  • ๋งค์šฐ ํฐ Heap (32GB+): ZGC, Shenandoah
  • ์ €์ง€์—ฐ ํ•„์ˆ˜: ZGC

์‹ค์ˆ˜ 7: System.gc() ๋กœ GC ๊ฐ•์ œ

public void process() {
    // ์ฒ˜๋ฆฌ
    System.gc();  // โŒ ๊ถŒ์žฅ X
}

๋ฌธ์ œ:

  • JVM ์ด ๋ฌด์‹œํ•  ์ˆ˜๋„ ์žˆ์Œ
  • Full GC โ†’ ๊ธด STW
  • ์„ฑ๋Šฅ ์˜ํ–ฅ

์›์น™: GC ๋Š” JVM ์ด ์•Œ์•„์„œ.


๐Ÿ”— 8. ์—ฐ๊ด€ ๊ฐœ๋… ๋งต

Phase 5 (GC) ๋‚ด ํ๋ฆ„

[Unit 5.1: GC ๊ธฐ๋ณธ + ์•ฝํ•œ ์„ธ๋Œ€ ๊ฐ€์„ค] โœ“
        โ†“
[Unit 5.2: Heap ์˜ ์„ธ๋Œ€ ๊ตฌ์กฐ] โœ“
        โ†“
[Unit 5.3: GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ 4๊ฐ€์ง€] โ† ์ง€๊ธˆ ์—ฌ๊ธฐ โ˜…
        โ†“
[Unit 5.4: GC ์ข…๋ฅ˜์™€ ์„ ํƒ ๊ธฐ์ค€] (๋งˆ์ง€๋ง‰)

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ง„ํ™” ์ •๋ฆฌ

์‹œ๊ธฐ์•Œ๊ณ ๋ฆฌ์ฆ˜์ฃผ์š” ๊ฐœ์„ 
1950sReference Counting์ฆ‰์‹œ ํšŒ์ˆ˜
1960sMark-Sweep์ˆœํ™˜ ์ฐธ์กฐ ํ•ด๊ฒฐ
1970sMark-Sweep-Compact๋‹จํŽธํ™” ํ•ด๊ฒฐ
1980sGenerationalํšจ์œจ โ†‘
1990sConcurrent (CMS)STW ์งง์Œ
2010sG1 (Region)ํฐ Heap
2010sZGC๋งค์šฐ ์งง์€ STW

๋‹ค๋ฅธ ์–ธ์–ด์™€์˜ ๋น„๊ต

์–ธ์–ดGC ์•Œ๊ณ ๋ฆฌ์ฆ˜
JavaGenerational + Mark-Sweep-Compact + Copying
C#/.NETGenerational + Mark-Sweep-Compact (๋น„์Šท)
GoConcurrent Mark-Sweep (์ €์ง€์—ฐ ์šฐ์„ )
PythonReference Counting + Cycle Detector
JavaScript (V8)Generational + Mark-Sweep
RubyMark-Sweep-Compact + Generational
RustGC ์—†์Œ (์†Œ์œ ๊ถŒ)

๋ฉด์ ‘ ๋‹จ๊ณจ ์งˆ๋ฌธ ๋งคํ•‘

์งˆ๋ฌธ์ด Unit์—์„œ์˜ ๋‹ต
"GC ์•Œ๊ณ ๋ฆฌ์ฆ˜?"RC, Mark-Sweep, MSC, Generational
"์™œ ์ž๋ฐ”๋Š” RC ์•ˆ ์”€?"์ˆœํ™˜ ์ฐธ์กฐ + ์นด์šดํŠธ ๋น„์šฉ
"Mark-Sweep ๋‹จ์ ?"๋‹จํŽธํ™”
"์ž๋ฐ” GC ์˜ ํŠน์ง•?"Generational + ์˜์—ญ๋ณ„ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜
"Copying GC?"Young ์˜์—ญ์—์„œ ์‚ฌ์šฉ

๐Ÿ“ 9. ํ•ต์‹ฌ ์š”์•ฝ โ€” 3์ค„ ์ •๋ฆฌ

1๏ธโƒฃ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ 4๊ฐ€์ง€ โ€” Reference Counting, Mark-Sweep, Mark-Sweep-Compact, Generational.

Reference Counting ์€ ์ฐธ์กฐ ์นด์šดํŠธ๋กœ ์ฆ‰์‹œ ํšŒ์ˆ˜, ์ˆœํ™˜ ์ฐธ์กฐ ์‹œ ๋ˆ„์ˆ˜. Mark-Sweep ์€ GC Root ์ถ”์ ์œผ๋กœ ๋งˆํ‚น ํ›„ ํšŒ์ˆ˜, ๋‹จํŽธํ™” ๋ฐœ์ƒ. Mark-Sweep-Compact ์€ ์••์ถ• ์ถ”๊ฐ€๋กœ ๋‹จํŽธํ™” ํ•ด์†Œ. Generational ์€ ์•ฝํ•œ ์„ธ๋Œ€ ๊ฐ€์„ค๋กœ ์˜์—ญ๋ณ„ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ ์šฉ.

2๏ธโƒฃ ์ž๋ฐ”๋Š” Generational + ์˜์—ญ๋ณ„ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•œ๋‹ค.

Young ์˜์—ญ (Eden + Survivor) ์€ Copying GC โ€” Eden + From ์˜ ์‚ด์•„์žˆ๋Š” ๊ฐ์ฒด๋ฅผ To ๋กœ ๋ณต์‚ฌ, ์ž๋™ ์••์ถ•. Old ์˜์—ญ์€ Mark-Sweep-Compact โ€” ๋งˆํ‚น + ํšŒ์ˆ˜ + ์••์ถ•. Reference Counting ์€ ์‚ฌ์šฉ X (์ˆœํ™˜ ์ฐธ์กฐ + ์นด์šดํŠธ ๋น„์šฉ ๋•Œ๋ฌธ). Card Table + Write Barrier ๋กœ Old โ†’ Young ์ฐธ์กฐ ์ถ”์ .

3๏ธโƒฃ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ํƒ = ํšจ์œจ / ๋‹จํŽธํ™” / STW ์˜ trade-off.

Reference Counting: ์ฆ‰์‹œ ํšŒ์ˆ˜, ๋ฉˆ์ถค X / ์ˆœํ™˜ ์ฐธ์กฐ ๋ˆ„์ˆ˜. Mark-Sweep: ๋‹จ์ˆœ, ์•ˆ์ „ / ๋‹จํŽธํ™”. Compact: ๋‹จํŽธํ™” ํ•ด์†Œ / STW ๊ธธ์–ด์ง. Generational: ์•ฝํ•œ ์„ธ๋Œ€ ๊ฐ€์„ค๋กœ ๊ท ํ˜• / ๊ตฌ์กฐ ๋ณต์žก. Java ์˜ ๋ชจ๋“  GC (Serial, Parallel, CMS, G1, ZGC) ๊ฐ€ Generational + ์ถ”๊ฐ€ ์ตœ์ ํ™”. ์šด์˜ ์‹œ G1 (๊ท ํ˜•) ๋˜๋Š” ZGC (์ €์ง€์—ฐ) ๊ถŒ์žฅ.


๐ŸŽ“ ํ•™์Šต ์ž๊ธฐ ์ ๊ฒ€

๊ธฐ๋ณธ ์ดํ•ด

  • 4๊ฐ€์ง€ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋‚˜์—ดํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๊ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ•ต์‹ฌ ๋™์ž‘์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๊ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์žฅ๋‹จ์ ์„ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค
  • ์ž๋ฐ”๊ฐ€ ์ฑ„ํƒํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์•ˆ๋‹ค (Generational)

์‹ค์ „ ์ ์šฉ

  • ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์ž๋ฐ”์—์„œ ์•ˆ์ „ํ•œ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋‹จํŽธํ™” ๋ฌธ์ œ๋ฅผ ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ILIC ์šด์˜์— ์ ํ•ฉํ•œ GC ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค
  • GC ๋กœ๊ทธ์—์„œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค

๋ฉด์ ‘ ๋Œ€๋น„ (5๋ถ„ ๋‹ต๋ณ€)

  • "GC ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ข…๋ฅ˜?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "์™œ ์ž๋ฐ”๋Š” RC ์•ˆ ์“ฐ๋‚˜์š”?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "Mark-Sweep ์˜ ๋‹จ์ ?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "Generational ์ด ํšจ์œจ์ ์ธ ์ด์œ ?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ

์ž๊ธฐ ์ ๊ฒ€ ์งˆ๋ฌธ ๋‹ต๋ณ€

Q1: ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ Reference Counting ์—์„œ ์™œ ๋ฌธ์ œ์ธ์ง€ ๊ทธ๋ฆผ์œผ๋กœ ๊ทธ๋ ค๋ณด๋ผ.

๋‹ต: ์™ธ๋ถ€ ์ฐธ์กฐ๊ฐ€ ๋ชจ๋‘ ๋Š๊ฒผ๋Š”๋ฐ, ๊ฐ์ฒด๋ผ๋ฆฌ ์ƒํ˜ธ ์ฐธ์กฐ ํ•˜๋ฉด ์นด์šดํŠธ๊ฐ€ 0 ์•ˆ ๋ผ์„œ ๋ˆ„์ˆ˜.

์ƒ์„ธ ์‹œ๊ฐํ™”:

Step 1: ์ •์ƒ ์ƒํƒœ

[Stack]
  alice (๋ณ€์ˆ˜)
  bob (๋ณ€์ˆ˜)

[Heap]
  Person "Alice"  cnt=1 (alice ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)
  Person "Bob"    cnt=1 (bob ์ด ๊ฐ€๋ฆฌํ‚ด)

Step 2: ์ƒํ˜ธ ์ฐธ์กฐ ์ถ”๊ฐ€

alice.friend = bob;  // bob: cnt=2 (alice.friend ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)
bob.friend = alice;  // alice: cnt=2 (bob.friend ๊ฐ€ ๊ฐ€๋ฆฌํ‚ด)
[Stack]
  alice โ”€โ”€โ”€โ”€โ”
  bob โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”
            โ”‚ โ”‚
[Heap]      โ–ผ โ–ผ
  Person "Alice"  cnt=2 โ”€โ”€โ†’ Person "Bob"  cnt=2
       โ†‘                          โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Step 3: ์™ธ๋ถ€ ์ฐธ์กฐ ๋Š์Œ

alice = null;  // alice ๊ฐ์ฒด: cnt=2-1=1
bob = null;    // bob ๊ฐ์ฒด: cnt=2-1=1
[Stack] (๋น„์–ด์žˆ์Œ)

[Heap]
  Person "Alice"  cnt=1 โ”€โ”€โ†’ Person "Bob"  cnt=1
       โ†‘                          โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
       
       ๋‘ ๊ฐ์ฒด ๋ชจ๋‘ cnt=1 (์„œ๋กœ ๊ฐ€๋ฆฌํ‚ด)
       โ†’ ์˜์›ํžˆ cnt=0 ์•ˆ ๋จ
       โ†’ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ โŒ

ํ•ต์‹ฌ ๋ฌธ์ œ:

  • ์™ธ๋ถ€์—์„œ๋Š” ๋„๋‹ฌ ๋ถˆ๊ฐ€ (์‚ฌ์šฉ ์ค‘ X)
  • ๊ทธ๋Ÿฌ๋‚˜ ์นด์šดํŠธ 0 ์•ˆ ๋จ
  • โ†’ Reference Counting ๋งŒ์œผ๋กœ ์ฒ˜๋ฆฌ ๋ถˆ๊ฐ€

ํ•ด๊ฒฐ์ฑ…๋“ค:

1. Cycle Detection (Python ์˜ ๋ณด์กฐ)

์ฃผ๊ธฐ์ ์œผ๋กœ:
  - ์นด์šดํŠธ 0 ์•ˆ ๋์ง€๋งŒ ๋„๋‹ฌ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด ์‹๋ณ„
  - ๊ทธ๊ฒƒ๋“ค ํšŒ์ˆ˜

2. Mark-Sweep (์ž๋ฐ”์˜ ์„ ํƒ)

GC Root ์—์„œ ์‹œ์ž‘
โ†’ alice, bob ๊ฐ์ฒด ๋„๋‹ฌ ๋ถˆ๊ฐ€
โ†’ Mark ์•ˆ ๋จ
โ†’ Sweep ์‹œ ํšŒ์ˆ˜

3. Weak Reference (์•ฝํ•œ ์ฐธ์กฐ)

class Person {
    WeakReference<Person> friend;  // ์•ฝํ•œ ์ฐธ์กฐ
    // โ†’ ์นด์šดํŠธ ์ฆ๊ฐ€ X
    // โ†’ ์ˆœํ™˜ ์ฐธ์กฐ ๋ฐœ์ƒ X
}

โ†’ ์ž๋ฐ”๋Š” Mark-Sweep ์œผ๋กœ ์šฐ์•„ํ•˜๊ฒŒ ํ•ด๊ฒฐ.


Q2: Mark-and-Sweep ์—์„œ OOM ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š”?

ํ•œ ์ค„ ๋‹ต: ๋‹จํŽธํ™” (Fragmentation) ๋•Œ๋ฌธ์— ํฐ ์—ฐ์† ๊ณต๊ฐ„ ๋ถ€์กฑ.

์ƒ์„ธ ์„ค๋ช…:

Mark-Sweep ๋งŒ ์‚ฌ์šฉ ์‹œ Compact ๋‹จ๊ณ„ ์—†์Œ:

Step 1: ์ดˆ๊ธฐ ์ƒํƒœ

[Heap] (1GB)
  [๊ฐ์ฒดA 100MB][๊ฐ์ฒดB 100MB][๊ฐ์ฒดC 100MB][๊ฐ์ฒดD 100MB][๊ฐ์ฒดE 100MB]
  ... 10๊ฐœ 100MB ๊ฐ์ฒด๋กœ ๊ฐ€๋“

Step 2: GC ๋ฐœ์ƒ โ€” ์ง์ˆ˜ ๊ฐ์ฒด๋งŒ Live

Mark:
  A (Live), B (Garbage), C (Live), D (Garbage), E (Live), ...

Sweep:
  [A 100MB][_ 100MB][C 100MB][_ 100MB][E 100MB][_ 100MB]...
            โ† ๋นˆ ๊ณต๊ฐ„๋“ค ํฉ์–ด์ง

Step 3: ํฐ ๊ฐ์ฒด ํ• ๋‹น ์‹œ๋„

byte[] big = new byte[300 * 1024 * 1024];  // 300MB

๋ฌธ์ œ:

  • Heap ์˜ ๋นˆ ๊ณต๊ฐ„ ์ดํ•ฉ = 500MB (์ถฉ๋ถ„ํ•ด ๋ณด์ž„)
  • ๊ทธ๋Ÿฌ๋‚˜ ์—ฐ์†๋œ ๋นˆ ๊ณต๊ฐ„ = 100MB ๊ฐ€ ์ตœ๋Œ€
  • 300MB ์—ฐ์† ๊ณต๊ฐ„ ์—†์Œ
  • โ†’ OOM โš ๏ธ

์‹œ๊ฐํ™”:

๋นˆ ๊ณต๊ฐ„๋“ค:
  100MB(B) + 100MB(D) + 100MB(F) + 100MB(H) + 100MB(J) = 500MB

๊ทธ๋Ÿฌ๋‚˜ ์œ„์น˜:
  [A][__][C][__][E][__][G][__][I][__]
      โ†‘ ์—ฐ์† 100MB ๋งŒ

โ†’ "๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ" ์ด ์•„๋‹Œ "์—ฐ์†๋œ ๊ณต๊ฐ„ ๋ถ€์กฑ".


๋น„์œ  โ€” ์ฃผ์ฐจ์žฅ์˜ ๋‹จํŽธํ™”

์ฃผ์ฐจ์žฅ (10๋Œ€ ์ฃผ์ฐจ ๊ฐ€๋Šฅ):
  [์ฐจ1][_][์ฐจ3][_][์ฐจ5][_][์ฐจ7][_][์ฐจ9][_]

๋นˆ ์ž๋ฆฌ: 5๊ฐœ (์ ˆ๋ฐ˜ ๋น„์–ด์žˆ์Œ)
๊ทธ๋Ÿฌ๋‚˜ ํŠธ๋Ÿญ (3๋Œ€ ์ž๋ฆฌ ํ•„์š”):
  โ†’ ์—ฐ์† 3๋Œ€ ์ž๋ฆฌ ์—†์Œ
  โ†’ ์ฃผ์ฐจ ๋ถˆ๊ฐ€ โš ๏ธ

ํ•ด๊ฒฐ์ฑ… โ€” Compact

Compact ํ›„:
  [์ฐจ1][์ฐจ3][์ฐจ5][์ฐจ7][์ฐจ9][_][_][_][_][_]
                          โ† ์—ฐ์†๋œ ๋นˆ ๊ณต๊ฐ„

์ด์ œ ํŠธ๋Ÿญ ์ฃผ์ฐจ ๊ฐ€๋Šฅ โœ…

์ž๋ฐ”์˜ ์‹ค์ œ

์ž๋ฐ”์˜ Old GC = Mark-Sweep-Compact:

  • Compact ๋‹จ๊ณ„๋กœ ๋‹จํŽธํ™” ํ•ด์†Œ
  • ์—ฐ์†๋œ ํฐ ๊ณต๊ฐ„ ํ™•๋ณด
  • ํฐ ๊ฐ์ฒด ํ• ๋‹น ๊ฐ€๋Šฅ

โ†’ ์ž๋ฐ”๊ฐ€ Mark-Sweep-Compact ์ฑ„ํƒํ•œ ์ด์œ .


G1 ์˜ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ

G1 GC ๋Š” Region ๊ธฐ๋ฐ˜:

  • Heap ์„ ์ž‘์€ Region ์œผ๋กœ ๋ถ„ํ• 
  • ๊ฐ Region ์•ˆ์—์„œ ์••์ถ•
  • ๋˜๋Š” Region ํ†ต์งธ๋กœ ํšŒ์ˆ˜

G1 ์˜ Humongous Object:

  • Region ์˜ ์ ˆ๋ฐ˜ ์ด์ƒ ๊ฐ์ฒด
  • ๋ณ„๋„ ์ฒ˜๋ฆฌ
  • โ†’ ๋‹จํŽธํ™” ๋ฌธ์ œ ์ ์Œ

๋‹ค์Œ Unit์œผ๋กœ

  • GC ์ข…๋ฅ˜์™€ ์„ ํƒ ๊ธฐ์ค€ ์„ ํ•™์Šตํ•  ์ค€๋น„ ์™„๋ฃŒ
  • Serial, Parallel, CMS, G1, ZGC ์˜ ์ฐจ์ด๊ฐ€ ๊ถ๊ธˆํ•˜๋‹ค
  • ์šด์˜ ํ™˜๊ฒฝ์—์„œ ์–ด๋–ค GC ๋ฅผ ์„ ํƒํ• ์ง€ ๋งŒ๋‚  ์ค€๋น„ ์™„๋ฃŒ
profile
Software Developer

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