728x90

1. Garbage Collection(GC)์ด๋ž€?

GC๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ํšŒ์ˆ˜ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ
C#, Java ๊ฐ™์€ ๊ด€๋ฆฌํ˜• ์–ธ์–ด ์—์„œ ์ œ๊ณต๋จ

๊ธฐ๋ณธ ๊ฐœ๋…
- ํž™(Heap) ์˜์—ญ์— ํ• ๋‹น๋œ ๊ฐ์ฒด ์ค‘ ๋” ์ด์ƒ ์ฐธ์กฐ๋˜์ง€ ์•Š๋Š” ๊ฐ์ฒด๋ฅผ ์ฐพ์•„์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšŒ์ˆ˜ํ•จ
- ์ˆ˜๋™ ํ•ด์ œ๊ฐ€ ํ•„์š” ์—†๋Š” ๋Œ€์‹ , GC ํƒ€์ด๋ฐ์— ๋”ฐ๋ผ ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

2. GC ๋™์ž‘ ๋ฐฉ์‹ (C# ๊ธฐ์ค€)

Mark and Sweep ๋ฐฉ์‹
1. Mark : ๋ฃจํŠธ(Root) ๊ฐ์ฒด์—์„œ ์‹œ์ž‘ํ•ด ์ฐธ์กฐ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋ฅผ ๋ชจ๋‘ โ€œ์‚ด์•„์žˆ๋‹คโ€๊ณ  ํ‘œ์‹œ
2. Sweep : ํ‘œ์‹œ๋˜์ง€ ์•Š์€ ๊ฐ์ฒด๋Š” ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ œ๊ฑฐ

์„ธ๋Œ€๋ณ„ ๊ด€๋ฆฌ(Generational GC)
- Generation 0 : ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด (๋น ๋ฅด๊ฒŒ ์ˆ˜๊ฑฐ)
- Generation 1 : ์กฐ๊ธˆ ์˜ค๋ž˜๋œ ๊ฐ์ฒด
- Generation 2 : ์˜ค๋ž˜ ์‚ด์•„๋‚จ์€ ๊ฐ์ฒด (GC ๋Œ€์ƒ์—์„œ ์ œ์™ธ๋˜๊ธฐ ์‰ฌ์›€)
-> ๋Œ€๋ถ€๋ถ„์˜ GC๋Š” Gen 0 ๋Œ€์ƒ์ด ๋งŽ๊ณ , Gen 2๋Š” ์ž˜ ์•ˆ ์ง€์›Œ์ง

GC Alloc

๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ, GC๊ฐ€ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋ฉด์„œ ์„ฑ๋Šฅ ์ €ํ•˜ ์œ ๋ฐœ
GC๊ฐ€ ์‹คํ–‰๋˜๋Š” ์ˆœ๊ฐ„ Stop-the-world(์ž ๊น์˜ ๋ฉˆ์ถค)์ด ๋ฐœ์ƒ


GC ๋ฐœ์ƒ ์˜ˆ์‹œ

void Update() {
    string msg = "Score: " + score; // ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ์ƒˆ string ์ƒ์„ฑ โ†’ GC Alloc
}


Unity์—์„œ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” GC ์›์ธ

1. string ์—ฐ๊ฒฐ : ๋ฌธ์ž์—ด์€ ๋ถˆ๋ณ€(immutable) ๊ฐ์ฒด๋ผ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง
2. List<T>.Add() : ๋‚ด๋ถ€ ๋ฐฐ์—ด์ด ๋„˜์น˜๋ฉด ์ƒˆ๋กœ์šด ๋ฐฐ์—ด ์ƒ์„ฑ
3. foreach : IEnumerator ๋ฐ•์‹ฑ ๋ฐœ์ƒ ๊ฐ€๋Šฅ
4. LINQ ์‚ฌ์šฉ : ๋ฌด์กฐ๊ฑด ํž™ ํ• ๋‹น ๋ฐœ์ƒ
5. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ๋žŒ๋‹ค ๋“ฑ๋ก ํ›„ ํ•ด์ œ ์•ˆํ•จ : ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์œ„ํ—˜

4. GC ์ตœ์†Œํ™” ์ „๋žต

(1) ๊ฐ์ฒด ํ’€๋ง (Object Pooling)

- ์ž์ฃผ ์ƒ์„ฑ/์ œ๊ฑฐ๋˜๋Š” ๊ฐ์ฒด๋Š” ํ’€๋กœ ๊ด€๋ฆฌ
- ์˜ˆ : ์ด์•Œ, ์ดํŽ™ํŠธ, UI ํ† ์ŠคํŠธ ๋“ฑ
Unity์—์„œ๋Š” UnityEngine.Pool.ObjectPool<T> ์‚ฌ์šฉ ๊ฐ€๋Šฅ

(2) ๊ตฌ์กฐ์ฒด ์‚ฌ์šฉ ๋ฐ ๊ฐ’ ํƒ€์ž… ํ™œ์šฉ

- ํด๋ž˜์Šค ๋Œ€์‹  struct ์‚ฌ์šฉ (ํž™ ํ• ๋‹น ํ”ผํ•จ)
- ๋‹จ, ๊ตฌ์กฐ์ฒด๋Š” ๋ณต์‚ฌ ๋น„์šฉ ์žˆ์œผ๋‹ˆ ์‹ ์ค‘ํ•˜๊ฒŒ ์‚ฌ์šฉ

(3) StringBuilder ํ™œ์šฉ


(4) NativeArray, Job System ์‚ฌ์šฉ

- Unity DOTS ํ™˜๊ฒฝ์—์„œ๋Š” GC ์—†๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
- NativeArray, NativeList ๋“ฑ์€ GC ๋ฐœ์ƒ ์—†์ด ์ž‘์—… ๊ฐ€๋Šฅ

5. Unity์—์„œ GC ๋ชจ๋‹ˆํ„ฐ๋ง ํŒ

- Profiler -> Memory -> GC Alloc ํ™•์ธ
- Deep Profiling ์„ ์ผœ๋ฉด ์–ด๋–ค ์ฝ”๋“œ์—์„œ GC๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์ถ”์  ๊ฐ€๋Šฅ
- Profiler.BeginSample("Tag")์œผ๋กœ ์ˆ˜๋™ ํƒœ๊น… ๊ฐ€๋Šฅ




๋ฐ˜์‘ํ˜•
728x90

1. ์บ์‹œ๋ž€?

CPU๋Š” ๋งค์šฐ ๋น ๋ฅด์ง€๋งŒ, RAM์€ ์ƒ๋Œ€์ ์œผ๋กœ ๋Š๋ฆผ
๊ทธ๋ž˜์„œ CPU์™€ RAM ์‚ฌ์ด์— ์ž‘์€ ๊ณ ์† ๋ฉ”๋ชจ๋ฆฌ์ธ โ€œ์บ์‹œ(Cache)"๊ฐ€ ์กด์žฌํ•จ
- L1,L2,L3 ์บ์‹œ : ์ ์  ๋Š๋ฆฌ์ง€๋งŒ ํฌ๊ธฐ๋Š” ์ปค์ง
- CPU๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•  ๋•Œ:
  - ์บ์‹œ์— ์žˆ์œผ๋ฉด -> Cache Hit (๋น ๋ฆ„)
  - ์—†์œผ๋ฉด -> Cache Miss (๋Š๋ฆผ, RAM๊นŒ์ง€ ๋‚ด๋ ค๊ฐ)

2. Cache Hit vs Cache Miss

- Cache Hit : CPU๊ฐ€ ์ฐพ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์บ์‹œ์— ์ด๋ฏธ ์กด์žฌ : ๋น ๋ฆ„ (์ˆ˜ ns)
- Cache Miss : CPU๊ฐ€ ์ฐพ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์บ์‹œ์— ์—†์Œ -> RAM์—์„œ ๊ฐ€์ ธ์˜ด (์ˆ˜์‹ญ~์ˆ˜๋ฐฑ ns)

3. Spatial & Temporal Locality (์ง€์—ญ์„ฑ)

CPU ์บ์‹œ๋Š” ์ง€์—ญ์„ฑ(Locality)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™ํ•จ
- Temporal Locality (์‹œ๊ฐ„์  ์ง€์—ญ์„ฑ):
  - ์ตœ๊ทผ ์‚ฌ์šฉํ•œ ๋ฐ์ดํ„ฐ๋Š” ๋˜ ์‚ฌ์šฉํ•  ๊ฐ€๋Šฅ์„ฑ ๋†’์Œ
- Spatial Locality (๊ณต๊ฐ„์  ์ง€์—ญ์„ฑ):
  - ์ธ์ ‘ํ•œ ๋ฐ์ดํ„ฐ๋„ ๊ฐ™์ด ์‚ฌ์šฉํ•  ๊ฐ€๋Šฅ์„ฑ ๋†’์Œ
๊ทธ๋ž˜์„œ CPU๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ, ๊ทผ์ฒ˜ ๋ฉ”๋ชจ๋ฆฌ ๋ฉ์–ด๋ฆฌ(=Cache Line) ์ „์ฒด๋ฅผ ๋ฏธ๋ฆฌ ๋ถˆ๋Ÿฌ์˜ด (๋ณดํ†ต ํ•œ cache line์€ 64๋ฐ”์ดํŠธ)

4. ์บ์‹œ ๋ฏธ์Šค๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ

- ๋ถˆ์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ
- ๋ฌด์ž‘์œ„ ํฌ์ธํ„ฐ ์ ‘๊ทผ
- ํฐ ๊ตฌ์กฐ์ฒด๋ฅผ ์ง€๋‚˜์น˜๊ฒŒ ๋ณต์‚ฌ
- ๋‹ค์ค‘ ์“ฐ๋ ˆ๋“œ์—์„œ ๋™์ผํ•œ ์บ์‹œ๋ผ์ธ ์ ‘๊ทผ (false sharing)

5. Unity/ECS ๊ด€์ ์—์„œ

ECS + Chunk ๊ตฌ์กฐ๋Š” ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋””์ž์ธ๋จ
- Chunk๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋จ
- ๋”ฐ๋ผ์„œ for-loop๋กœ ์ˆœํšŒํ•  ๋•Œ Cache Hit๊ฐ€ ๊ทน๋Œ€ํ™”
- ๋ฐ˜๋Œ€๋กœ, GameOjbect + MonoBehaviour๋Š” ๊ฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฐ๋ฐœ์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ์Œ -> Cache Miss ์ž์ฃผ ๋ฐœ์ƒ

6. ์˜ˆ์‹œ ์ฝ”๋“œ ๋น„๊ต (Cache Friendly vs Cache Unfriendly)

[Cache Unfriendly]

class Unit {
    public float posX, posY, velX, velY;
}

Unit[] units = new Unit[100000];

for (int i = 0; i < units.Length; i++) {
    units[i].posX += units[i].velX;
}

-> ๊ฐ Unit์ด ๋ฉ”๋ชจ๋ฆฌ ์ƒ ํฉ์–ด์ ธ ์žˆ์–ด ์บ์‹œ ๋ฏธ์Šค ๋ฐœ์ƒ

[Cache Friendly - ECS ์Šคํƒ€์ผ]

struct Position { public float x, y; }
struct Velocity { public float x, y; }

NativeArray<Position> positions;
NativeArray<Velocity> velocities;

for (int i = 0; i < positions.Length; i++) {
    positions[i].x += velocities[i].x;
}

-> ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ, ์บ์‹œ ํžˆํŠธ์œจ ๋†’์Œ

- CPU ์บ์‹œ๋Š” RAM๋ณด๋‹ค ๋น ๋ฅธ ์ค‘๊ฐ„ ์ €์žฅ์†Œ
- Cache Hit = ๋น ๋ฅด๊ฒŒ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
- Cache Miss = RAM ์ ‘๊ทผ -> ๋Š๋ ค์ง
- ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ & ์ง€์—ญ์„ฑ ๊ณ ๋ ค๊ฐ€ ํ•ต์‹ฌ
- Unity ECS๋Š” ์บ์‹œ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์„ค๊ณ„๋จ

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ์„ฑ๋Šฅ ์ตœ์ ํ™” : False Sharing๊ณผ Data Alignment ์ดํ•ดํ•˜๊ธฐ

1. False Sharing (๊ฐ€์งœ ๊ณต์œ )

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ํ™˜๊ฒฝ์—์„œ ๋‘ ๊ฐœ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ์ ‘๊ทผํ•œ๋‹ค๊ณ  ํ•ด๋„, ๊ทธ ๋ฐ์ดํ„ฐ๋“ค์ด ๊ฐ™์€ ์บ์‹œ ๋ผ์ธ(Cache Line)์— ์กด์žฌํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Œ
์™œ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š”๊ฐ€?
- CPU๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹œ ๋ผ์ธ ๋‹จ์œ„(64๋ฐ”์ดํŠธ ๋“ฑ)๋กœ ๋ถˆ๋Ÿฌ์˜ด
- ์Šค๋ ˆ๋“œ A๊ฐ€ ๋ณ€์ˆ˜ a๋ฅผ ์ˆ˜์ • -> ๊ฐ™์€ ์บ์‹œ ๋ผ์ธ์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ B์˜ ๋ณ€์ˆ˜ b๋„ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ฌดํšจํ™”๋จ
- ๊ทธ ๊ฒฐ๊ณผ, CPU๋Š” ์บ์‹œ๋ฅผ ๊ณ„์† ๋™๊ธฐํ™”(sync)ํ•ด์•ผ ํ•˜๋ฉฐ, ์„ฑ๋Šฅ ์ €ํ•˜๋กœ ์ด์–ด์ง

์˜ˆ์‹œ

public class SharedData
{
    public int a; // Thread 1 ์‚ฌ์šฉ
    public int b; // Thread 2 ์‚ฌ์šฉ
}

- a์™€ b๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์‚ฌ์šฉํ•˜์ง€๋งŒ, ๊ฐ™์€ 64๋ฐ”์ดํŠธ ์ •๋„)์— ๋“ค์–ด๊ฐ€ ์žˆ์„ ํ™•๋ฅ ์ด ๋†’์Œ
- Thread 1์ด a๋ฅผ ์ˆ˜์ • -> CPU๋Š” a๊ฐ€ ์žˆ๋Š” ์บ์‹œ ๋ผ์ธ์„ ๋‹ค๋ฅธ ์ฝ”์–ด์™€ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•จ
- ๊ทธ ๊ฒฐ๊ณผ Thread 2๋„ b์— ์ ‘๊ทผํ•  ๋•Œ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์บ์‹œ ๋ฏธ์Šค๋‚˜ ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฐœ์ƒ

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:
- ์บ์‹œ ๋ผ์ธ ํŒจ๋”ฉ(Padding)์„ ๋„ฃ์–ด์„œ ๋ถ„๋ฆฌ์‹œํ‚ด
๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ์บ์‹œ๋ผ์ธ์— ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ

[StructLayout(LayoutKind.Explicit, Size = 128)] // 64๋ฐ”์ดํŠธ ์ด์ƒ์œผ๋กœ ๋ถ„๋ฆฌ
public struct PaddedInt
{
    [FieldOffset(64)] public int value;
}

- StructLayout์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ธ์œ„์ ์œผ๋กœ ๋„์›Œ์„œ false sharing ๋ฐฉ์ง€
- Unity์—์„œ๋„ ๋น„์Šทํ•œ ๋ฐฉ์‹์˜ ์บ์‹œ ๋ผ์ธ ํŒจ๋”ฉ ๊ธฐ๋ฒ•์ด ์‚ฌ์šฉ๋จ

๋˜๋Š” Unity์˜ Burst/Jobs์—์„œ๋Š”:

[StructLayout(LayoutKind.Sequential)]
public struct Counter1 : IJob
{
    [NativeDisableParallelForRestriction]
    public NativeArray<int> array;

    public void Execute()
    {
        array[0]++;
    }
}

-> NativeArray<int>์—์„  false sharing์ด ๋‚  ์ˆ˜ ์žˆ์œผ๋‹ˆ index๋งˆ๋‹ค 64๋ฐ”์ดํŠธ ์ •๋„ ๋„์›Œ์„œ ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ NativeArray<CustomPaddedStruct>๋ฅผ ์‚ฌ์šฉ


2. Data Alignment (๋ฐ์ดํ„ฐ ์ •๋ ฌ)

์ •์˜:
CPU๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ํŠน์ • ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ •๋ ฌ๋˜์–ด ์žˆ์–ด์•ผ ํšจ์œจ์ ์œผ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅ
์ž˜ ์ •๋ ฌ๋œ ๋ฐ์ดํ„ฐ๋Š” ํ•œ ๋ฒˆ์— ์ฝ์„ ์ˆ˜ ์žˆ์Œ, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์—ฌ๋Ÿฌ ๋ฒˆ ์ฝ๊ฑฐ๋‚˜ ๋Š๋ ค์ง

struct A {
    byte a;
    int b;
}


- ์œ„ ๊ตฌ์กฐ์ฒด์—์„œ byte a๋Š” 1๋ฐ”์ดํŠธ์ง€๋งŒ, int b๋Š” 4๋ฐ”์ดํŠธ ์ •๋ ฌ์ด ํ•„์š”ํ•จ -> ์‚ฌ์ด์— 3๋ฐ”์ดํŠธ ํŒจ๋”ฉ์ด ์ž๋™ ์‚ฝ์ž… ๋จ

Unity์—์„œ ์ฃผ์˜ํ•  ์ :

- IComponentData ๊ตฌ์กฐ์ฒด๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ 4,8,16๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ •๋ ฌํ•˜๋Š” ๊ฒŒ ์ข‹์Œ
- float3๋Š” 16๋ฐ”์ดํŠธ ์ •๋ ฌ๋จ -> ๋’ค์— int๊ฐ€ ์˜ค๋ฉด ๋ถˆํ•„์š”ํ•œ ์ •๋ ฌ๋น„์šฉ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

์ •๋ ฌ ์ตœ์ ํ™”

// ๋‚˜์œ ์˜ˆ
struct Bad {
    public int a;
    public byte b;
    public float3 c;
}

// ์ข‹์€ ์˜ˆ
struct Good {
    public float3 c;
    public int a;
    public byte b;
}




๋ฐ˜์‘ํ˜•
728x90

1. ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ์ด๋ž€?

๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋ฉ”๋ชจ๋ฆฌ์— ์ ‘๊ทผํ•  ๋•Œ์˜ ๊ทœ์น™๊ณผ ๋ณด์žฅ ๋ฒ”์œ„๋ฅผ ์ •์˜ํ•œ ๊ฒƒ
- ์šฐ๋ฆฌ๊ฐ€ x = 10 ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์“ด๋‹ค๊ณ  ํ•ด๋„, ์‹ค์ œ ์‹คํ–‰ ์ˆœ์„œ๋‚˜ ์ฝ๋Š” ๊ฐ’์€ CPU, ์ปดํŒŒ์ผ๋Ÿฌ, ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™”์— ์˜ํ•ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ
-> ์–ธ์ œ ์–ด๋–ค ๊ฐ’์ด ๋ณด์žฅ๋˜๋Š”์ง€? -> ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ์ด ์ด๊ฑธ ์ •์˜ํ•ด์„œ ์คŒ

2. ์™œ ์ค‘์š”ํ•œ๊ฐ€?

๋ฉ€ํ‹ฐ์ฝ”์–ด CPU์—์„œ๋Š” ๊ฐ ์ฝ”์–ด๋งˆ๋‹ค ์บ์‹œ๊ฐ€ ์žˆ์Œ
-> ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ฐ”๋กœ RAM์—์„œ ์ฝ์ง€ ์•Š๊ณ , ์ž๊ธฐ ์บ์‹œ์—์„œ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ์Œ
-> ๊ทธ๋Ÿฌ๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊น€:
A ์ฝ”์–ด๊ฐ€ x=10 ํ–ˆ๋Š”๋ฐ, B ์ฝ”์–ด๋Š” x๊ฐ€ 0์ธ์ค„ ์•Œ๊ณ  ์ž˜๋ชป๋œ ๊ณ„์‚ฐ์„ ํ•  ์ˆ˜ ์žˆ์Œ

3. Cache Coherency (์บ์‹œ ์ผ๊ด€์„ฑ)

๋ฉ€ํ‹ฐ์ฝ”์–ด CPU๋Š” ์ฝ”์–ด๋“ค ๊ฐ„ ์บ์‹œ์˜ ๊ฐ’์„ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•จ
-> ์ด๊ฑธ ์บ์‹œ ์ผ๊ด€์„ฑ(coherency)๋ผ๊ณ  ํ•จ

๋Œ€ํ‘œ์ ์ธ ํ”„๋กœํ† ์ฝœ : MESI (Modified, Exclusive, Shared, Invalid)
-> ๊ฐ ์บ์‹œ ๋ผ์ธ์ด ์–ด๋–ค ์ƒํƒœ์ธ์ง€ ์ถ”์ ํ•ด์„œ
-> ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋‹ค๋ฅธ ์ฝ”์–ด๋“ค์—๊ฒŒ ์•Œ๋ฆผ (Invalidation)

4. CPU/์ปดํŒŒ์ผ๋Ÿฌ์˜ ๋ช…๋ น์–ด ์žฌ๋ฐฐ์น˜ ๋ฌธ์ œ

- CPU๋‚˜ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์„ฑ๋Šฅ์„ ์œ„ํ•ด ๋ช…๋ น์–ด ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๊ธฐ๋„ ํ•จ
- a = 1; b = 2; -> ์‹ค์ œ๋กœ๋Š” b = 2; a = 1; ์ด ๋จผ์ € ์‹คํ–‰๋  ์ˆ˜๋„ ์žˆ์Œ
- ๋‹จ์ผ ์“ฐ๋ ˆ๋“œ์—์„  ๋ฌธ์ œ ์—†์ง€๋งŒ, ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ์—์„  Race Condition ๋ฐœ์ƒ ๊ฐ€๋Šฅ

5. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•: ๋ฉ”๋ชจ๋ฆฌ ๋ฐฐ๋ฆฌ์–ด & volatile

5-1. Memory Barrier (๋ฉ”๋ชจ๋ฆฌ ์žฅ๋ฒฝ)

- CPU๊ฐ€ ๋ช…๋ น์–ด ์ˆœ์„œ ์žฌ๋ฐฐ์น˜๋ฅผ ํ•˜์ง€ ์•Š๋„๋ก ๋ง‰๋Š” ๋ช…๋ น
- ์ข…๋ฅ˜
  - Load Barrier: ์ฝ๊ธฐ ์ˆœ์„œ ๊ณ ์ •
  - Store Barrier: ์“ฐ๊ธฐ ์ˆœ์„œ ๊ณ ์ •
  - Full Barrier: ์ฝ๊ธฐ/์“ฐ๊ธฐ ๋ชจ๋‘ ์ˆœ์„œ ๊ณ ์ •

5-2. volatile ํ‚ค์›Œ๋“œ (C#)

- ๋ณ€์ˆ˜์— volatile์„ ๋ถ™์ด๋ฉด:
  - ํ•ญ์ƒ ๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ฝ๊ณ  ์”€
  - CPU ์บ์‹œ/์ปดํŒŒ์ผ๋Ÿฌ ์ตœ์ ํ™” ๋ฐฉ์ง€
  - ๋‹จ์  : ์™„์ „ํ•œ ๋™๊ธฐํ™”๋Š” ์•ˆ ๋จ (lock์€ ์•„๋‹˜)

6. .NET ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ ์š”์•ฝ

- C#์˜ lock, Interlocked, volatile์€ ๋ชจ๋‘ ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ ๋ณด์žฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘
- lock์€ ๋‚ด๋ถ€์ ์œผ๋กœ Memory Barrier๊ฐ€ ํฌํ•จ๋จ -> ์•ˆ์ •์ 
- Interlocked๋„ ์›์ž์ (๋”์ด์ƒ ์ชผ๊ฐค์ˆ˜ ์—†๋Š”) ์—ฐ์‚ฐ + ๋ฉ”๋ชจ๋ฆฌ ๋ฒ ๋ฆฌ์–ด๋ฅผ ์ž๋™ ์‚ฝ์ž…

7. Unity์—์„œ๋Š”?

- Unity๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋ชจ๋“  API ๋™์ž‘์ด ์ด๋ฃจ์–ด์ง
- ํ•˜์ง€๋งŒ Job System, Burst, NativeArray ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•:
  - ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์ˆœ์„œ์™€ ์บ์‹œ ๋™๊ธฐํ™”์— ์‹ ๊ฒฝ ์จ์•ผ ํ•จ
  - Unity์˜ Jobs.WithReadOnly(), NativeContatiner ํŠน์„ฑ์€ ๋ฉ”๋ชจ๋ฆฌ ์ผ๊ด€์„ฑ์„ ์œ„ํ•œ ํžŒํŠธ ์—ญํ• ์„ ํ•จ

Burst Compiler๋ž€?
์š”์•ฝ
C# ์ฝ”๋“œ๋ฅผ ๋„ค์ดํ‹ฐ๋ธŒ ๋จธ์‹ ์ฝ”๋“œ๋กœ ์ปดํŒŒ์ผํ•ด์ฃผ๋Š” Unity ์ „์šฉ ๊ณ ์† ์ปดํŒŒ์ผ๋Ÿฌ
ํŠน์ง•
- JIT์ด ์•„๋‹ˆ๋ผ AOT (Ahead of Time) ๋ฐฉ์‹
- ์ผ๋ฐ˜ C# ์ฝ”๋“œ๋ณด๋‹ค ์ˆ˜์‹ญ ๋ฐฐ ๋น ๋ฅผ ์ˆ˜ ์žˆ์Œ
- SIMD(๋ฒกํ„ฐ ๋ช…๋ น์–ด)์™€ CPU ์บ์‹œ ์ตœ์ ํ™”๋ฅผ ์ ๊ทน ์‚ฌ์šฉ
- Unity Editor์—์„œ๋Š” Burst๊ฐ€ ์ ์šฉ๋œ ํ•จ์ˆ˜๋Š” ์ฆ‰์‹œ ํ™•์ธ ๊ฐ€๋Šฅ

[BurstCompile]
public struct MyJob : IJob
{
    public void Execute()
    {
        // ๊ณ ์† ์‹คํ–‰ ์ฝ”๋“œ
    }
}

์žฅ์ 
- CPU ๋ช…๋ น ์ตœ์ ํ™”
- ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์ตœ์†Œํ™”
- ์“ฐ๋ ˆ๋“œ ์•ˆ์ „ ๋ณด์žฅ

Job System์ด๋ž€?

์š”์•ฝ
Unity๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ์ž‘์—… ์‹œ์Šคํ…œ
-> ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ๋ง‰์ง€ ์•Š๊ณ , ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋™์‹œ์— ์‹คํ–‰ ๊ฐ€๋Šฅ
๊ธฐ๋ณธ ๊ฐœ๋…
- IJob : ๋‹จ์ผ ์ž‘์—… (์ž‘์—… ๋‹จ์œ„)
- IJobParallelFor : ๋ณ‘๋ ฌ ๋ฐ˜๋ณต (for ๋ฃจํ”„๋ฅผ ๋‹ค์ค‘ ์ฝ”์–ด์— ๋ถ„์‚ฐ)
- IJobChunk : ECS์—์„œ ์“ฐ๋Š” ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ์šฉ Job


์žฅ์ 
- ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ํ•ด๋ฐฉ
- Unity๊ฐ€ ์ž๋™์œผ๋กœ ์ž‘์—…์„ ์“ฐ๋ ˆ๋“œํ’€์— ๋ถ„๋ฐฐ
- Burst + Job ์กฐํ•ฉ์œผ๋กœ ์—„์ฒญ๋‚œ ์„ฑ๋Šฅ ํ™•๋ณด ๊ฐ€๋Šฅ

NativeArray๋ž€?

์š”์•ฝ
Unity์˜ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์ธ ๋ฐฐ์—ด ๊ตฌ์กฐ์ฒด
C#์˜ List<T>, Array๋ณด๋‹ค ๋น ๋ฅด๊ณ  ๋ฒ„์ŠคํŠธ/์žก ์‹œ์Šคํ…œ์— ์ตœ์ ํ™”๋จ
ํŠน์ง•
- GC๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ
- ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ -> CPU ์บ์‹œ ์นœํ™”์ 
- ๋ฐ˜๋“œ์‹œ Dispose()๋กœ ์ˆ˜๋™ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ ํ•„์š”

Unity DOTS ์ƒํƒœ๊ณ„ ์š”์•ฝ

- ECS : ๊ตฌ์กฐ ์ž์ฒด๋ฅผ ๋ฐ์ดํ„ฐ ์ง€ํ–ฅ์ ์œผ๋กœ
- Job System : ๋‹ค์ค‘ ์ž‘์—… ์Šค์ผ€์ค„๋ง
- Burst Compiler : ์‹คํ–‰ ์„ฑ๋Šฅ ๊ทน๋Œ€ํ™”
- Native Collections : GC ์—†๋Š” ๊ตฌ์กฐ

Unity DOTS ์ „์ฒด ๊ฐœ๋… ์š”์•ฝ

DOTS๋Š” Data-Oriente Technology Stack์˜ ์•ฝ์ž
๋ชฉํ‘œ๋Š” ์ˆ˜์‹ญ๋งŒ ๊ฐœ ์˜ค๋ธŒ์ ํŠธ๋„ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ

ECS ๊ตฌ์กฐ ํ•ต์‹ฌ ์ •๋ฆฌ

ECS๋Š” OOP์™€ ๋ฐ˜๋Œ€๋˜๋Š” ๊ฐœ๋…
Entity์— ๋ฐ์ดํ„ฐ๋งŒ ๋ถ€์ฐฉ
์‹œ์Šคํ…œ(System)์ด ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ ์ˆœํšŒ ์ฒ˜๋ฆฌ
์ˆœ์ฐจ์  ๋ฐ์ดํ„ฐ ์ค‘์‹ฌ (์บ์‹œ ์นœํ™”์ )

public struct Position : IComponentData {
    public float3 Value;
}

public struct Velocity : IComponentData {
    public float3 Value;
}

public partial class MoveSystem : SystemBase {
    protected override void OnUpdate() {
        float dt = Time.DeltaTime;
        Entities
            .ForEach((ref Position pos, in Velocity vel) =>
            {
                pos.Value += vel.Value * dt;
            }).ScheduleParallel(); // Job + Burst ์ ์šฉ ๊ฐ€๋Šฅ
    }
}

Chunk ๊ตฌ์กฐ

ECS๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ๋™์ผํ•œ Archetype (์ปดํฌ๋„ŒํŠธ ์กฐํ•ฉ)์˜ ์—”ํ‹ฐํ‹ฐ๋“ค์„ Chunk๋ผ๋Š” ๋ฉ์–ด๋ฆฌ์— ์ €์žฅํ•จ
- ํ•˜๋‚˜์˜ Chunk = ์ˆ˜์‹ญ ๊ฐœ ~ ์ˆ˜๋ฐฑ ๊ฐœ ์—”ํ‹ฐํ‹ฐ
- ๋ฉ”๋ชจ๋ฆฌ ์—ฐ์† = CPU ์บ์‹œ์— ์™„์ „ ์ตœ์ ํ™”
- System์€ Chunk ๋‹จ์œ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœํšŒํ•จ

Transform, Velocity, Health๊ฐ€ ๊ฐ™์ด ์žˆ๋Š” Entity๋Š” ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก์— ์ •๋ ฌ๋จ

Job + Burst๊ฐ€ ๋ถ™์œผ๋ฉด ์ƒ๊ธฐ๋Š” ์ผ

- SystemBase์˜ .ScheduleParallel()์€ ๋‚ด๋ถ€์ ์œผ๋กœ Job์„ ์ƒ์„ฑํ•จ
- ์ด Job์€ Burst๋กœ ์ปดํŒŒ์ผ๋˜๋ฉด ๋„ค์ดํ‹ฐ๋ธŒ SIMD ๋ช…๋ น์–ด๋กœ ์ตœ์ ํ™”๋ผ์„œ, ์ˆ˜๋ฐฑ ๊ฐœ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ•œ ๋ฒˆ์— ๋ฐ€์–ด๋ƒ„ -> ์—„์ฒญ ๋น ๋ฆ„

์ตœ์ ํ™” ์š”๋ น

- IComponentData๋งŒ ์‚ฌ์šฉ : ์ฐธ์กฐํ˜•๋ณด๋‹ค valueํ˜• ๊ตฌ์กฐ์ฒด ์‚ฌ์šฉ
- SharedComponentData๋Š” ์‹ ์ค‘ํ•˜๊ฒŒ ์‚ฌ์šฉ : Chunk ๋ถ„ํ• ์„ ์œ ๋ฐœํ•˜๋ฏ€๋กœ
- Archetype ์กฐํ•ฉ ์ตœ์†Œํ™” : Chunk ํŒŒํŽธํ™”๋ฅผ ๋ฐฉ์ง€
- System์€ ScheduleParallel ์šฐ์„  ์‚ฌ์šฉ : ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํšจ์œจ ์ฆ๊ฐ€
- NativeArray์— BurstCompile ์ ์šฉ : ์—ฐ์‚ฐ ์„ฑ๋Šฅ ๊ทน๋Œ€ํ™”
- math ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ ๊ทน ํ™œ์šฉ : float3, dot, normalize ๋“ฑ SIMD ์ตœ์ ํ™”๋จ

DOTS ํ๋ฆ„ ์˜ˆ์‹œ

1. ์—”ํ‹ฐํ‹ฐ ์ƒ์„ฑ
2. System์ด ๋ชจ๋“  Entity ์ˆœํšŒ
3. ์ปดํฌ๋„ŒํŠธ ์กฐํ•ฉ์— ๋”ฐ๋ผ Chunk ๋‹จ์œ„๋กœ ์ˆœํšŒ
4. Job System์ด ์“ฐ๋ ˆ๋“œ๋กœ ๋ถ„์‚ฐ ์ฒ˜๋ฆฌ
5. Burst๊ฐ€ ๋‚ด๋ถ€ ์—ฐ์‚ฐ์„ SIMD ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ ์† ์‹คํ–‰

๊ฐœ๋ฐœ์ž๊ฐ€ ์‹ ๊ฒฝ ์จ์•ผ ํ•  ๋ถ€๋ถ„

- ๊ตฌ์กฐ์ฒด๋กœ ์„ค๊ณ„ (์ฐธ์กฐ ์ง€์–‘)
- ์ปดํฌ๋„ŒํŠธ ์กฐํ•ฉ์„ ์ผ์ •ํ•˜๊ฒŒ ์œ ์ง€
- NativeArray, NativeList ์‚ฌ์šฉ ์‹œ Dispose ์ฒ˜๋ฆฌ
- ์Šค๋ ˆ๋“œ ์„ธ์ดํ”„ํ•œ Job ์„ค๊ณ„
- Debug ๋กœ๊ทธ ์‚ฌ์šฉ ์‹œ Burst ์„ฑ๋Šฅ ์ €ํ•˜ ์ฃผ์˜





๋ฐ˜์‘ํ˜•
728x90

1. ๊ฒฝ์Ÿ์กฐ๊ฑด์ด๋ž€?

๋‘ ๊ฐœ ์ด์ƒ์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๊ณต์œ  ์ž์›(์˜ˆ: ๋ณ€์ˆ˜, ๋ฆฌ์ŠคํŠธ ๋“ฑ)์— ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ ค ํ•  ๋•Œ, ์‹คํ–‰ ์ˆœ์„œ์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์ง€๋Š” ๋ฌธ์ œ

์˜ˆ์‹œ

int counter = 0;

Thread t1 = new Thread(()=> {
	for(int i=0; i<1000; i++) counter++;
});

Thread t2 = new Thread(()=> {
	for(int i=0; i<1000; i++) counter++;
});

t1.Start();
t2.Start();


๊ธฐ๋Œ€๊ฐ’์€ 2000์ด์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” 1500 ~ 2000 ์‚ฌ์ด์˜ ๊ฐ’์ด ๋‚˜์˜ฌ ์ˆ˜๋„ ์žˆ์Œ
์›์ž์ (atomic) ์—ฐ์‚ฐ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ

์›์ž์ (atomic) ์—ฐ์‚ฐ์ด๋ž€?

ํ•˜๋‚˜์˜ ์—ฐ์‚ฐ์ด โ€œ๋” ์ด์ƒ ์ชผ๊ฐค ์ˆ˜ ์—†๋Š” ๋‹จ์œ„โ€๋กœ ์ˆ˜ํ–‰๋˜๋Š” ๊ฒƒ
- ์‹คํ–‰ ์ค‘ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋ผ์–ด๋“ค ์ˆ˜ ์—†๊ณ ,
- ๋ฐ˜๋“œ์‹œ ์ „๋ถ€ ์„ฑ๊ณตํ•˜๊ฑฐ๋‚˜, ์ „๋ถ€ ์‹คํŒจํ•จ. ์ค‘๊ฐ„ ์ƒํƒœ๊ฐ€ ์—†์Œ
์ฆ‰, โ€œํ•œ ๋ฒˆ์— ๋”ฑ ์ฒ˜๋ฆฌ๋œ๋‹คโ€ ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋จ

์™œ counter++๋Š” ์›์ž์ ์ด์ง€ ์•Š์€๊ฐ€?

counter++๋Š” 3๋‹จ๊ณ„๋กœ ๋‚˜๋‰˜๋Š” ์—ฐ์‚ฐ์ž„
1. counter ๊ฐ’์„ ์ฝ์Œ (read)
2. ๊ฐ’์— 1์„ ๋”ํ•จ (add)
3. ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ์ €์žฅํ•จ (write)
-> ์ด ์ค‘๊ฐ„์— ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๊ฐ€ counter ๊ฐ’์„ ๋ฐ”๊ฟ”๋ฒ„๋ฆด ์ˆ˜ ์žˆ์Œ
-> ๊ทธ๋ž˜์„œ ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„  ์˜๋„ํ•œ ๊ฐ’์ด ๋‚˜์˜ค์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ

2. ํฌ๋ฆฌํ‹ฐ์ปฌ ์„น์…˜(Critical Section)

์ •์˜
๊ฒฝ์Ÿ ์กฐ๊ฑด์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ ๋ธ”๋Ÿญ
-> ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜์˜ ์“ฐ๋ ˆ๋“œ๋งŒ ์‹คํ–‰ํ•ด์•ผ ์•ˆ์ „ํ•จ

3. ๋™๊ธฐํ™” ๊ธฐ๋ฒ•๋“ค

3-1. Mutex (Mutual Exclusion)

- ํ”„๋กœ์„ธ์Šค ๊ฐ„ ๋˜๋Š” ์“ฐ๋ ˆ๋“œ ๊ฐ„ ๋ฝ์„ ๊ฑธ๊ธฐ ์œ„ํ•œ ๋ฐฉ์‹
- ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์“ฐ๋ ˆ๋“œ๋งŒ ๋ฎคํ…์Šค๋ฅผ ์†Œ์œ  ๊ฐ€๋Šฅ

3-2. Monitor / lock (C#์—์„œ ๊ฐ€์žฅ ํ”ํ•จ)

- ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” Monitor.Enter/Exit ๊ธฐ๋ฐ˜
- lock์€ ์“ฐ๊ธฐ ํŽธํ•˜๊ณ  ์Šค์ฝ”ํ”„ ๊ธฐ๋ฐ˜ ํ•ด์ œ๊ฐ€ ๋ณด์žฅ๋ผ์„œ ์•ˆ์ „ํ•จ

class Counter
{
    private int _count = 0;
    private readonly object _lock = new object();

    public void Increment()
    {
        lock (_lock)
        {
            _count++;
        }
    }

    public int GetValue()
    {
        lock (_lock)
        {
            return _count;
        }
    }
}


3-3. Semaphore

- ๋ฎคํ…์Šค๋Š” ํ•œ ๋ฒˆ์— 1๊ฐœ ์“ฐ๋ ˆ๋“œ๋งŒ ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ์ง€๋งŒ,
- ์„ธ๋งˆํฌ์–ด๋Š” ๋™์‹œ ํ—ˆ์šฉ ์ˆ˜ ์ œํ•œ์ด ์žˆ์Œ (์˜ˆ: ๋™์‹œ์— 3๊ฐœ๊นŒ์ง€ ์ง„์ž… ํ—ˆ์šฉ)

3-4. SpinLock

- Lock์„ ๊ฑธ ๋•Œ, ์Šค๋ ˆ๋“œ๊ฐ€ ๋Œ€๊ธฐ ์ƒํƒœ๋กœ ๋ฉˆ์ถ”๋Š” ๋Œ€์‹  ๊ณ„์† ๋ฃจํ”„๋ฅผ ๋Œ๋ฉด์„œ ํ™•์ธํ•˜๋Š” ๋ฐฉ์‹
- CPU ๋‚ญ๋น„๊ฐ€ ์žˆ์ง€๋งŒ, ์งง์€ ๋ฝ ๊ตฌ๊ฐ„์—์„œ ๋น ๋ฅธ ๋ฐ˜์‘์„ฑ์ด ์žˆ์Œ

4. ๋ฐ๋“œ๋ฝ(Deadlock)์ด๋ž€?

๋‘ ๊ฐœ ์ด์ƒ์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์„œ๋กœ ์ƒ๋Œ€๋ฐฉ์˜ ๋ฝ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ์—์„œ ๋น ์ ธ๋‚˜์˜ค์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ

์˜ˆ์‹œ
- Thread A๊ฐ€ Lock1์„ ์žก๊ณ  Lock2๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ ,
- Thread B๊ฐ€ Lock2๋ฅผ ์žก๊ณ  Lock1์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒฝ์šฐ -> ๋‘˜ ๋‹ค ๋ฉˆ์ถค

์˜ˆ๋ฐฉ ๋ฐฉ๋ฒ•:
- ํ•ญ์ƒ ๋ฝ์„ ๊ณ ์ •๋œ ์ˆœ์„œ๋กœ ํš๋“
- ํƒ€์ž„์•„์›ƒ ์„ค์ •์œผ๋กœ ํƒˆ์ถœ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์„ค๊ณ„

5. Unity์—์„œ๋Š”?

Unity๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ์ค‘์‹ฌ ๊ตฌ์กฐ์ด์ง€๋งŒ,
- Job System + Burst๋ฅผ ์“ฐ๊ฑฐ๋‚˜
- Task, ThreadPool, BackgroundWorker ๋“ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ฒฝ์Ÿ ์กฐ๊ฑด ์ฃผ์˜ ํ•„์š”
Unity์˜ NativeArray๋Š” ์Šค๋ ˆ๋“œ ์•ˆ์ •ํ•˜์ง€ ์•Š์Œ -> NativeQueue ๊ฐ™์€ ๊ตฌ์กธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ Job System ๋‚ด์—์„œ๋งŒ ์ ‘๊ทผํ•ด์•ผ ํ•จ


๋ฐ˜์‘ํ˜•
728x90


CPU์™€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์ด์˜ ์†๋„ ์ฐจ์ด๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ๋„์ž…๋œ ๊ฒƒ์ด ์บ์‹œ(Cache)
๊ฒŒ์ž„์ฒ˜๋Ÿผ ์—ฐ์‚ฐ์ด ๋งŽ์€ ํ™˜๊ฒฝ์—์„œ๋Š” ์บ์‹œ์˜ ํ™œ์šฉ์ด ์„ฑ๋Šฅ์— ์—„์ฒญ๋‚œ ์˜ํ–ฅ์„ ์คŒ

1. ์™œ ์บ์‹œ๊ฐ€ ํ•„์š”ํ• ๊นŒ?

- CPU๋Š” ์—„์ฒญ ๋น ๋ฆ„
- RAM(๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ)์€ ์ƒ๋Œ€์ ์œผ๋กœ ๋Š๋ฆผ
- ๋งค๋ฒˆ RAM์— ์ ‘๊ทผํ•˜๋ฉด ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฐœ์ƒ
-> ๊ทธ๋ž˜์„œ CPU ๊ทผ์ฒ˜์— ๋” ๋น ๋ฅด๊ณ  ์ž‘์€ ๊ธฐ์–ต์žฅ์น˜์ธ ์บ์‹œ๋ฅผ ๋‘ฌ์„œ ์„ฑ๋Šฅ์„ ๋†’์ž„

2. ์บ์‹œ ๋ฉ”๋ชจ๋ฆฌ ๊ณ„์ธต ๊ตฌ์กฐ

๋ณดํ†ต ์บ์‹œ๋Š” L1 -> L2 -> L3 ์ˆœ์„œ๋กœ ๊ตฌ์„ฑ๋จ
๊ณ„์ธต / ์œ„์น˜ / ํฌ๊ธฐ / ์†๋„ / ์—ญํ• 
L1 / CPU ๋‚ด๋ถ€ / ์ ์Œ(์ˆ˜์‹ญ KB) / ๊ฐ€์žฅ ๋น ๋ฆ„ / ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ๋ช…๋ น๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ
L2 / CPU ๋‚ด๋ถ€ or ์™ธ๋ถ€ / ์ˆ˜๋ฐฑ KB~MB / L1๋ณด๋‹ค ๋Š๋ฆผ / L1์—์„œ ๋ชป ์ฐพ์„ ๋•Œ ์‚ฌ์šฉ
L3 / CPU ์™ธ๋ถ€ (๊ณต์œ ) / ์ˆ˜ MB / L2๋ณด๋‹ค ๋Š๋ฆผ / ๋ชจ๋“  ์ฝ”์–ด๊ฐ€ ๊ณต์œ 

* RAM์€ ์บ์‹œ ๋ฏธ์Šค๊ฐ€ ๋‚ฌ์„ ๋•Œ ์ ‘๊ทผํ•˜๋Š” ์ฃผ ๊ธฐ์–ต์žฅ์น˜

3. ์บ์‹œ ํžˆํŠธ vs ์บ์‹œ ๋ฏธ์Šค

- ์บ์‹œ ํžˆํŠธ (Cache Hit)
-> ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์บ์‹œ์— ์žˆ์Œ -> ๋น ๋ฅด๊ฒŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
- ์บ์‹œ ๋ฏธ์Šค (Cache Miss)
-> ์บ์‹œ์— ๋ฐ์ดํ„ฐ ์—†์Œ -> RAM ์ ‘๊ทผ -> ์†๋„ ๋Š๋ฆผ

๊ฒŒ์ž„์—์„œ ์บ์‹œ ๋ฏธ์Šค๊ฐ€ ์žฆ์œผ๋ฉด
- FPS ํ•˜๋ฝ
- ์ž…๋ ฅ ์ง€์—ฐ
- ๋ฌผ๋ฆฌ ์—ฐ์‚ฐ ๋Š๋ ค์ง

4. ์บ์‹œ ์นœํ™”์ ์ธ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ (Cache-Friendly)

CPU๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•จ

๊ตฌ์กฐ์ฒด ์„ค๊ณ„ ํŒ
- SoA (Structure of Arrays) -> ์บ์‹œ ํšจ์œจ ๋†’์Œ
- AoS (Array of Structures) -> ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์Œ

5. ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์—์„œ ์บ์‹œ ํ™œ์šฉ ์˜ˆ์‹œ

- Physics Simulation : ์ถฉ๋Œ ํŒ์ • ๊ณ„์‚ฐ ์‹œ ์บ์‹œ ํšจ์œจ์ด ์ค‘์š”
- Animation : ๋ณธ ์ •๋ณด์™€ ํŠธ๋žœ์Šคํผ ์—ฐ์‚ฐ์„ ๋น ๋ฅด๊ฒŒ ๊ฐ€์ ธ์™€์•ผ ํ•จ
- AI Pathfinding : ๋…ธ๋“œ ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ ์‹œ ์บ์‹œ ์ตœ์ ํ™”
- Rendering : ๋ฒ„ํ…์Šค, ํ…์Šค์ฒ˜ ๋ฐ์ดํ„ฐ ์บ์‹ฑ

Unity ECS(Entity Component System)

1. ์ผ๋ฐ˜์ ์ธ OOP ๋ฐฉ์‹์˜ ๋ฌธ์ œ์  (MonoBehaviour ์ค‘์‹ฌ)

Unity์˜ ์ „ํ†ต์ ์ธ ๋ฐฉ์‹์€ OOP(Object-Oriented Programming)๋ฅผ ๋”ฐ๋ฅด๊ณ  ์žˆ์Œ
์ด ๊ฐ์ฒด๋“ค์ด ๋ฉ”๋ชจ๋ฆฌ์— ํฉ์–ด์ ธ ์žˆ์Œ (๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๊ฐ€ ๋ถˆ์—ฐ์†์ )
CPU์บ์‹œ ๋ฏธ์Šค ์ฆ๊ฐ€

2. CPU ์บ์‹œ๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋‚˜?

CPU๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ(RAM)์—์„œ ์ง์ ‘ ์ฝ๊ธฐ๋ณด๋‹ค, L1~L3 ์บ์‹œ์— ๋ฏธ๋ฆฌ ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉํ•จ
๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ์†๋œ ์ฃผ์†Œ(๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก)๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์—, ์บ์‹œ์— ๋“ค์–ด๊ฐ€๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋ณดํ†ต 64๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ๋ฌถ์—ฌ์„œ ์ฒ˜๋ฆฌ๊ฐ€ ๋จ (์บ์‹œ ๋ผ์ธ ๋‹จ์œ„)
๋”ฐ๋ผ์„œ ์—ฐ์†๋œ ๋ฐ์ดํ„ฐ ๊ตฌ์ฃŒ์ˆ˜๋ก ์บ์‹œ ์ ์ค‘๋ฅ (Cache Hit Rate)์ด ๋†’์Œ

3. Unity ECS์˜ ๊ตฌ์กฐ: SoA (Structure of Arrays)

Unity ECS๋Š” ๋ฐ์ดํ„ฐ๋ฅผ SoA (Structure of Arrays) ๋ฐฉ์‹์œผ๋กœ ์ €์žฅํ•จ
์ฆ‰, ์ปดํฌ๋„ŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ํฐ ๋ฐฐ์—ด์ฒ˜๋Ÿผ ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ์†์ ์œผ๋กœ ์ €์žฅํ•จ
Entity๋งˆ๋‹ค ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฐ€์ง€๋ฉฐ, ์ด ๋ฐ์ดํ„ฐ๋“ค์€ Chunk๋ผ๋Š” ๋‹จ์œ„๋กœ ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋จ
1Chunk = ์—ฌ๋Ÿฌ Entity์˜ ๋™์ผํ•œ ์ปดํฌ๋„ŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ •๋ ฌ๋œ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ๋ณด๊ด€
Chunk๋Š” ECS ๋‚ด๋ถ€์—์„œ ์ปดํฌ๋„ŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ณ ์ • ํฌ๊ธฐ์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก
ECS๋Š” ๋ชจ๋“  Entity์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ , ๋น„์Šทํ•œ ๊ตฌ์„ฑ์˜ Entity๋“ค์„ ๋ฌถ์–ด์„œ Chunk์— ์ €์žฅํ•จ
Chunk ํ•˜๋‚˜๋Š” ๋ณดํ†ต 16KB ํฌ๊ธฐ๋กœ ๊ณ ์ •๋˜์–ด ์žˆ์Œ (Unity ๊ธฐ๋ณธ ์„ค์ • ๊ธฐ์ค€)
Chunk๋Š” ๊ฐ™์€ Archetype(Entity ๊ตฌ์กฐ)๋ฅผ ๊ฐ€์ง„ Entity๋“ค์„ ๋‹ด๋Š” ์ปจํ…Œ์ด๋„ˆ
ํ•˜๋‚˜์˜ Chunk์— ๋‹ด๊ธด Entity๋“ค์€ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ๊ฐ–๊ณ  ์žˆ์Œ
์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ์†์ ์œผ๋กœ ์ •๋ ฌ๋œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๊ฐ€ ์ƒ๊ธฐ๊ณ , CPU ์บ์‹œ ํšจ์œจ์ด ๊ทน๋Œ€ํ™” ๋จ
โ€œCPU ์บ์‹œ๋ฅผ ๊ณ ๋ คํ•œ ๋ฌผ๋ฆฌ์  ์ •๋ ฌ ๋ฐฉ์‹โ€

์ด ๊ตฌ์กฐ๊ฐ€ ์™œ ๋น ๋ฅธ๊ฐ€?
์—ฐ์†๋œ ๋ฐฐ์—ด ์ˆœํšŒ -> ์บ์‹œ ํžˆํŠธ -> ๋ฒกํ„ฐํ™” ๊ธฐ๋Šฅ (SIMD) -> ์ดˆ๊ณ ์† ์ฒ˜๋ฆฌ

4. Burst Compiler์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•  ๋•Œ

ECS๋Š” ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋งŒ ๊ฐœ์„ ํ•œ ๊ฒŒ ์•„๋‹ˆ๋ผ, Burst Compiler์™€ ์กฐํ•ฉ๋˜๋ฉด ์„ฑ๋Šฅ์ด ๊ทน์ ์œผ๋กœ ํ–ฅ์ƒ๋จ
Burst๋Š” Low-level CPU ์ตœ์ ํ™”๋ฅผ ์ž๋™์œผ๋กœ ํ•ด์คŒ
์—ฐ์†๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋Œ€์ƒ์œผ๋กœ SIMD(Vectorization) ์ตœ์ ํ™”๋„ ์ ์šฉ
์บ์‹œ ํžˆํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฃจํ”„๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ธ๋ผ์ธํ™” & ํŒŒ์ดํ”„๋ผ์ธํ™”


๋ฐ˜์‘ํ˜•
728x90

๊ฒŒ์ž„ ๊ฐœ๋ฐœ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๊ฐ€ ์ œ๋Œ€๋กœ ์•ˆ๋˜๋ฉด?

- ํ”„๋ ˆ์ž„ ๋“œ๋ž
- ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜
- ๊ฒŒ์ž„ ํฌ๋ž˜์‹œ
๊ทธ๋ž˜์„œ ๊ฒŒ์ž„ ์—”์ง„๋“ค์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ์ ์šฉํ•˜๊ณ  ์žˆ์Œ

1. ๋™์  ํ• ๋‹น๊ณผ ์ •์  ํ• ๋‹น

์ •์  ํ• ๋‹น(Static Allocation)
- ์ปดํŒŒ์ผ ์‹œ๊ฐ„(๋นŒ๋“œ ์‹œ์ )์— ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ๊ฐ€ ๊ฒฐ์ •๋จ
- ์˜ˆ์‹œ : ๊ธ€๋กœ๋ฒŒ ๋ณ€์ˆ˜, ์ •์  ๋ณ€์ˆ˜, ์Šคํƒ ๋ณ€์ˆ˜

๋™์  ํ• ๋‹น(Dynamic Allocation)
- ์‹คํ–‰ ์ค‘(Run-time) ํ•„์š”ํ•œ ๋งŒํผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹น
- ์˜ˆ์‹œ : new(C++), malloc()(C), Instantiate()(Unity)

๊ฒŒ์ž„ ๊ฐœ๋ฐœ์—์„œ ์ค‘์š”ํ•œ ์ด์œ 
- ๋™์  ํ• ๋‹น์„ ๋„ˆ๋ฌด ๋งŽ์ด ํ•˜๋ฉด ํ”„๋ ˆ์ž„๋งˆ๋‹ค ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น/ํ•ด์ œ๊ฐ€ ๋ฐœ์ƒ -> ์„ฑ๋Šฅ ์ €ํ•˜
- ํ•ด๊ฒฐ์ฑ… : ๋ฉ”๋ชจ๋ฆฌ ํ’€(Memory Pool) ํ™œ์šฉ (์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ํ• ๋‹นํ•ด๋‘ )

2. ์Šคํƒ(Stack) vs. ํž™(Heap) ๋ฉ”๋ชจ๋ฆฌ

์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ(Stack)
- ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ ์ž๋™ ํ• ๋‹น๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„
- ํ• ๋‹น/ํ•ด์ œ ์†๋„๊ฐ€ ๋น ๋ฆ„
- ๋‹จ์  : ํฌ๊ธฐ๊ฐ€ ํ•œ์ •์ ์ด๊ณ , ๋„ˆ๋ฌด ๋งŽ์ด ์“ฐ๋ฉด ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ(Stack Overflow) ๋ฐœ์ƒ

ํž™ ๋ฉ”๋ชจ๋ฆฌ(Heap)
- new/malloc()๋กœ ๋™์  ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ
- ์ž์œ ๋กญ๊ฒŒ ํฌ๊ธฐ๋ฅผ ์กฐ์ ˆ ๊ฐ€๋Šฅ
- ๋‹จ์  : ํ• ๋‹น/ํ•ด์ œ ๋น„์šฉ์ด ํฌ๊ณ , ๋ฉ”๋ชจ๋ฆฌ ๋‹จํŽธํ™”(Fragmentation) ๋ฐœ์ƒ ๊ฐ€๋Šฅ

๊ฒŒ์ž„ ๊ฐœ๋ฐœ์—์„œ ์ค‘์š”ํ•œ ์ด์œ 
- ์‹ค์‹œ๊ฐ„ ๊ฒŒ์ž„์—์„œ๋Š” ํž™ ํ• ๋‹น์„ ์ตœ์†Œํ™”ํ•ด์•ผ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ์Œ
- ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ธฐ๋ฒ• : ์˜ค๋ธŒ์ ํŠธ ํ’€๋ง(Object Pooling) ํ™œ์šฉ

3. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ (Memory Leak)

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ž€?
- ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜์ง€ ์•Š์•„์„œ ์ ์  ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š” ํ˜„์ƒ
- ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด RAM์ด ๋ถ€์กฑํ•ด์„œ ๊ฒŒ์ž„์ด ํฌ๋ž˜์‹œ๋  ์ˆ˜ ์žˆ์Œ

๊ฒŒ์ž„ ๊ฐœ๋ฐœ์—์„œ ํ”ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์‚ฌ๋ก€
- new๋กœ ํ• ๋‹นํ•˜๊ณ  delete๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์Œ (C++)
- Unity์—์„œ GameObject.Destroy()๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ์ฐธ์กฐ๋ฅผ ๋‚จ๊ฒจ๋‘ 
- Unreal Engine์—์„œ UObject๊ฐ€ ์ ์ ˆํžˆ ๊ด€๋ฆฌ๋˜์ง€ ์•Š์Œ

์˜ˆ์ œ(C++ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐœ์ƒ ์ฝ”๋“œ)

void Function(){
	Data* data = new Data();	//๋™์  ํ• ๋‹น
	//ํ•ด์ œํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐœ์ƒ
}


ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•
- ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ(Smart Pointer) ์‚ฌ์šฉ (C++)
  - std::unique_ptr,std::shared_ptr
- Garbage Collector(GC) ์ตœ์ ํ™” (C#/Unity,UE4)
  - Resources.UnloadUnusedAssets() ์‚ฌ์šฉ
- ๋ฉ”๋ชจ๋ฆฌ ํ’€๋ง(Object Pooling) ํ™œ์šฉ

4. ๋ฉ”๋ชจ๋ฆฌ ๋‹จํŽธํ™” (Memory Fragmentation)

๋ฉ”๋ชจ๋ฆฌ ๋‹จํŽธํ™”๋ž€?
- ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก์ด ํŒŒํŽธ์ฒ˜๋Ÿผ ํฉ์–ด์ ธ ์žˆ์–ด์„œ ํฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ
- ์‹ค์‹œ๊ฐ„ ๊ฒŒ์ž„์—์„œ๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ ๋‹จํŽธํ™”๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํฐ ์˜ค๋ธŒ์ ํŠธ ๋กœ๋”ฉ์ด ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Œ

๊ฒŒ์ž„์—์„œ ๋‹จํŽธํ™”๋ฅผ ์ค„์ด๋Š” ๋ฐฉ๋ฒ•
- ๋ฉ”๋ชจ๋ฆฌ ํ’€๋ง(Memory Pooling) : ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ํ• ๋‹น
- ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ(Array vs. Linked List)
  - ๋ฐฐ์—ด์€ ์—ฐ์†๋œ ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์บ์‹œ ํšจ์œจ์ด ์ข‹์Œ
- ์ •์  ํ• ๋‹น ์šฐ์„  ์‚ฌ์šฉ

5. ๋ฉ”๋ชจ๋ฆฌ ์ตœ์ ํ™” ๊ธฐ๋ฒ• (๊ฒŒ์ž„ ๊ฐœ๋ฐœ ์ ์šฉ)

์˜ค๋ธŒ์ ํŠธ ํ’€๋ง(Object Pooling)
- ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ํ• ๋‹นํ•ด๋‘๊ณ , ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ฒ•
- ์˜ˆ์‹œ : ์ด์•Œ, ์  ์บ๋ฆญํ„ฐ, ์ดํŽ™ํŠธ

๋ฐ์ดํ„ฐ ๋ ˆ์ด์•„์›ƒ ์ตœ์ ํ™”(Cache-Friendly Design)
- ์—ฐ์†๋œ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ CPU ์บ์‹œ ๋ฏธ์Šค๋ฅผ ์ค„์ž„
- ์˜ˆ์‹œ : SoA(Structure of Arrays) vs. AoS(Array of Structures)

๋ฆฌ์†Œ์Šค ์ŠคํŠธ๋ฆฌ๋ฐ(Texture Streaming, Level Streaming)
- ํ•„์š”ํ•  ๋•Œ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•ด์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝ
- Unreal Engine, Unity๋Š” ๋น„๋™๊ธฐ ๋กœ๋”ฉ(Async Loading)์„ ์ œ๊ณต

์ •์  ํ• ๋‹น(Static Allocation) ํ™œ์šฉ
- ๊ฒŒ์ž„ ์‹œ์ž‘ ์‹œ ํ•œ ๋ฒˆ ํ• ๋‹นํ•˜๊ณ  ๋๊นŒ์ง€ ์œ ์ง€
- ๋ฌผ๋ฆฌ์ ์œผ๋กœ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ์˜ค๋ธŒ์ ํŠธ์— ์ ํ•ฉ

๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜(Garbage Collection) ๊ด€๋ฆฌ
- Unity: GC.Collect() ํ˜ธ์ถœ ์ตœ์†Œํ™”
- Unreal Engine: Garbage Collection์ด ์ž๋™์œผ๋กœ ์ž‘๋™ํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ํ™•์ธ ํ•„์ˆ˜

๋ฐ˜์‘ํ˜•

+ Recent posts