Unity ๋ Memory ์ฑ๋ฅ์ ์ํด 3๊ฐ์ง Memory ๋ฅผ ์ฌ์ฉํ๋ค.
1. Managed memory: Heap ๊ณผ Garbage Collector ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋์ผ๋ก ํ ๋น&ํด์ ํ๋ ๋ฉ๋ชจ๋ฆฌ
2. C# unmanaged memory: C# Collections package ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ก ๊ตฌํ ๋ฐ ๊ด๋ฆฌ ๊ฐ๋ฅ.
3. Native memory: Unity Engine ์ ์คํํ๋๋ฐ ์ฌ์ฉํ๋ C++ ๋ฉ๋ชจ๋ฆฌ. ์ฌ์ฉ์๊ฐ ์ง์ Access ํ ์๋ ์์ผ๋ ์๊ณ ๋ ์์ด์ผ ํ๋ ๋ถ๋ถ.
* Managed memory
Mono ์ IL2CPP ์ scripting virtual machines(VMs)์ Managed memory ๋ฅผ ์คํํ๋ค.
1) The managed heap: VMs ๊ฐ Garbage Collector ๋ก ์๋์ผ๋ก ์ปจํธ๋กคํ๋ ๋ฉ๋ชจ๋ฆฌ ๋ถ๋ถ.
๊ทธ๋์ managed heap ์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ GC Allocation ์ด๋ผ๊ณ ๋ถ๋ฆ ๋๋ค. GC Allocation ์ Profiler ๊ฐ ๊ธฐ๋กํ๋ค.
ํ์ ์ ์ ๊ณผ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋จํธํ๊ฐ ๋ฐ์ํ์ ๋, GC ๋ 1) ๋น๊ณต๊ฐ์ ๋จผ์ ๋ฃ๊ธฐ๋ฅผ ์๋ํ๊ณ , ์๋ ๊ฒฝ์ฐ 2) ํ์ ํ์ฅํฉ๋๋ค.
* ์ด ๋, ํ์ ์ด์ ๋ฉ๋ชจ๋ฆฌ์ 2๋ฐฐ ๋งํผ ํ์ฅ ๋ฉ๋๋ค. <- ์ด๊ฒ ๋ฌธ์
ex) reference ํ์
, boxing ๋ ๊ฐํ์ object.
2) The scripting stack: ์ฝ๋ ๋ฒ์ { } ์์์ ํ ๋น๋๊ณ ํด์ ๋๋ ๋ถ๋ถ.
3) Native VM memory: Unity Scripting Layer ์ ๊ด๋ จ๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํฌํจ๋๋ค. Generics ์ฌ์ฉ๊ณผ ๊ด๋ จ๋ ๋ฉ๋ชจ๋ฆฌ, reflection์ด ์ฌ์ฉํ๋ ๋ฉํ ๋ฐ์ดํฐ, VMs ์ ์คํํ๋๋ฐ ํ์ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํฌํจ๋์ด ์๋ค๋ ๊ฑด ์๊ณ ์์.
- Managed memory์ ์ฅ์ : ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์๋์ผ๋ก ํด์ค.
- Managed memory์ ๋จ์ : ๋ฉ๋ชจ๋ฆฌ ํด์ /ํ ๋น ๋ฐฉ์์ ์์ธกํ ์ ์์ด์ ๋ถ์์ ํ ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค. ์์ธก ๊ฐ๋ฅํด์ผ๋ง ํ๋ ๋ถ๋ถ์ C# unmanaged memory ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
* C# unmanaged memory
job system, burst ๋ฑ ๋ฉ๋ชจ๋ฆฌ ์์ธก์ด ๊ฐ๋ฅํด์ผํ ๊ฒฝ์ฐ C# Collection package ๋ฐ์ดํฐ ๊ตฌ์กฐ์ Allocator๋ฅผ ๋ก C# unmanaged memory ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
NativeArray<int> nums = new NativeArray<int>(10, Allocator.TempJob);
// Create and schedule a job that uses the array.
ExampleJob job = new ExampleJob { Nums = nums };
JobHandle handle = job.Schedule();
// Create and schedule a job that will dispose the array after the ExampleJob has run.
// Returns the handle of the new job.
handle = nums.Dispose(handle);
* Native memory
Unity ์์ง ๋ด๋ถ์ C/C++ ์ฝ์ด์ ์๋ Native Memory. Unity ์์ฒด ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์์คํ ์ด๋ค. ์ง์ ์ ๊ทผ์ ๋ถ๊ฐ๋ฅํ๋ Profiler Marker ๋ก ์ด ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น๋์ง ํ์ธํ ์ ์๋ค.
The managed heap ์์ ๋์๋ Garbage Collector ๊ฐ๋ ์ ์์ธํ ์ดํด๋ณด์.
*Garbage Collector: Unity ๊ฐ ๋์ด์ ์ฌ์ฉํ์ง ์๋ ๊ฐ์ฒด์์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ ํจ.
Heap ์ ํ ๋น์ ์๋ํ๋๋ฐ Heap์ ํ ๋น์ ์์ํ ์ฌ์ ๊ฐ ์์ ๊ฒฝ์ฐ Garbage Collector ๋ฅผ ์คํ ํจ.
Garbage Collector ๊ฐ ๋ ์ด์ ์ฐธ์กฐํ์ง ์๋ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ์ญ์ ํ์ฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ๋ณดํจ.
- Garbage Collector ์์ฑ 2๊ฐ์ง
1) Incremental garbage collector: Garbage Collector ํ๋ก์ธ์ค๋ฅผ ํ๋ฒ์ ์คํํ๋๊ฒ์ด ์๋๋ผ ์ฌ๋ฌ ํ๋ ์์ ๊ฑธ์ณ ์คํํ๋ค.
2) Incremental garbage collector disabled: Incremental GC ๋ฅผ ๋นํ์ฑํํ๋ฉด GC๊ฐ Heap ์ ๊ฐ์ฒด๋ฅผ ๊ฒ์ฌํ๊ณ ์ฒ๋ฆฌํ๊ธฐ ์ํด Application ์คํ์ ์ค์งํด๋ฒ๋ฆฐ๋ค.
=> GC ๋ฅผ ์ชผ๊ฐ์ ์คํํ๋ ๊ฒ์ด ๋์ ๊ณณ๊ณผ GC ๋ฅผ ํ๋ฒ์ ์คํํ๋ ๊ฒ์ด ๋์ ๋ถ๋ถ์ด ์๊ธฐ์ Incremental GC ๋ฅผ ์คํ์์ผ์ ํ๋ ์์ ๋จ์ดํธ๋ฆด ๊ฑด์ง ํ๋ ์์ด ์ด์ง ๋ฉ์ถ๋๋ผ๋ ํ๋ฒ์ ์ ๋ฆฌํ๋๊ฒ ๋์ ๊ฒ์ธ์ง ๊ณ ๋ฏผ์ด ํ์ํ๋ค.
3) Disable automatic garbage collector: ์๋ GC ์ฌ์ฉ ์ํจ. ์๋์ ๊ฐ์ ์ฝ๋๋ก GC ๋ฅผ ์คํํ๋ ์๊ธฐ๋ฅผ ์์ ํ ์ ์ดํ ์ ์๋ค.
// GC ํ์ฑํ
GarbageCollector.GCMode = GarbageCollector.Mode.Enabled;
// GC ๋นํ์ฑํ
GarbageCollector.GCMode = GarbageCollector.Mode.Disabled;
// ์ ์ง์ GC ์ฃผ๊ธฐ ์ค์
GarbageCollector.CollectIncremental(ulong nanoseconds);
* GC ์ Allocation ์ ์ถ์ ํ ์ ์๋ ๋ฐฉ๋ฒ
: Unity Profiler ์ CPU Usage module, Unity Profiler ์ Memory Module, The Memory Profiler package:
* GC ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ค์ด๋ ๋ฐฉ๋ฒ
1) Managed Heap ์ฌ์ฉ๋์ ์ค์ด์.
2) ์ฌ์ฌ์ฉ๊ฐ๋ฅํ Object Pool ์ ์ฌ์ฉํ์
3) ๋ฌธ์์ด์ ์ฐ๊ฒฐํ ๋ System.Text.StringBuilder ๋ฅผ ์ฌ์ฉํ์.
: C# ์ ๋ฌธ์์ด์ ๋ถ๋ณ์ฐธ์กฐ ์ ํ์ด๋ค. ๋ฐ๋ผ์ ๋ฌธ์์ด ๋ณ์๊ฐ ์ผ๋จ ์์ฑ๋๋ฉด ์์ ํ ๋ ์์ ํ ์๋ก์ด ๋ฌธ์์ด์ด ์์ฑ๋์ด Heap ์ ์ ์ฅ๋๋ค. ๋ฐ๋ผ์ ๋ฌธ์์ด์ ์ฐ๊ฒฐํด์ผ ํ๋ค๋ฉด System.Text.StringBuilder ์ฌ์ฉํ์.
using UnityEngine;
public class ExampleScript : MonoBehaviour {
string ConcatExample(string[] stringArray) {
string result = "";
for (int i = 0; i < stringArray.Length; i++) {
result += stringArray[i];
}
return result;
}
}
"A", "AB", "ABC", "ABCD", "ABCDE" ๊ฐ heap ์ ์ ์ฅ๋๋ค. "ABCDE" ๋ง ์์ผ๋ฉด ๋๋๋ฐ ๋๋จธ์ง ๊ฒ๋ค์ด ์ค๋ณต ํ ๋น ๋๋ ๊ฒ.
// Good C# script example: StringBuilder avoids creating temporary strings,
// and only allocates heap memory for the final result string.
using UnityEngine;
using System.Text;
public class ExampleScript : MonoBehaviour {
private StringBuilder _sb = new StringBuilder(16);
string ConcatExample(string[] stringArray) {
_sb.Clear();
for (int i = 0; i < stringArray.Length; i++) {
_sb.Append(stringArray[i]);
}
return _sb.ToString();
}
}
4) ๋ฐฐ์ด ๊ฐ์ ๋ฐํํ๋ ๋ฉ์๋๋ ๋ฐฐ์ด์ด reference type ์ด๋ผ๋ ๊ฒ์ ์ด์ฉํ์.
using UnityEngine;
using System.Collections;
public class ExampleScript : MonoBehaviour {
float[] RandomList(int numElements) {
var result = new float[numElements];
for (int i = 0; i < numElements; i++) {
result[i] = Random.value;
}
return result;
}
}
RandomList ํจ์๋ฅผ ํธ์ถํ ๋ ๋ง๋ค ๋ฐฐ์ด์ด ์์ฑ๋์ด heap ์ ํ ๋น๋๊ณ result ๋ฅผ ๋ฐํํ ํ์๋ result ๊ฐ์ด heap ์ ๋จ์ ์๋๋ค.
using UnityEngine;
using System.Collections;
public class ExampleScript : MonoBehaviour {
void RandomList(float[] arrayToFill) {
for (int i = 0; i < arrayToFill.Length; i++) {
arrayToFill[i] = Random.value;
}
}
}
์์ ๊ฐ์ด ์ธ์๋ก ๋ณด๋ด๋ฉด reference type ์ด๋ฏ๋ก ๋ฐฐ์ด์ ์ฌ์ฌ์ฉํ์ฌ heap ์ ์๋กญ๊ฒ ํ ๋น๋์ง ์๋๋ค.
5) Collection ๊ณผ Array ๋ฅผ ์ฌ์ฌ์ฉํ์.
void Update() {
List<float> nearestNeighbors = new List<float>();
findDistancesToNearestNeighbors(nearestNeighbors);
nearestNeighbors.Sort();
// … use the sorted list somehow …
}
์ ์ฝ๋๋ Update ๋ฌธ์ด ํธ์ถ๋ ๋ ๋ง๋ค List ๋ฅผ ๊ณ์ ์์ฑํ์ฌ Heap ์ ํ ๋นํ๋ค.
List<float> m_NearestNeighbors = new List<float>();
void Update() {
m_NearestNeighbors.Clear();
findDistancesToNearestNeighbors(NearestNeighbors);
m_NearestNeighbors.Sort();
// … use the sorted list somehow …
}
ํ๋ฒ ์์ฑํ List ๋ฅผ ์ฌ์ฌ์ฉํ์ฌ ์ฌ์ฉํ๋ฉด Heap ์ ์๋ก ํ ๋นํ์ง ์๋๋ค.
6) Boxing ์ ํผํ์.
: Boxing ์ ์์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ์ผ๋ฐ์ ์ธ ์์ธ ์ค์ ํ๋๋ค. Value ์ ํ์ ๋ณ์๊ฐ Reference ์ ํ์ผ๋ก ๋ณํ๋ ๋ ๋ฐ์ํ๋ค.
int x = 1;
object y = new object();
y.Equals(x);
7) Array-valued Unity APIs๋ฅผ ์ฌ์ฉํ ๋ single array allocation ์ ์ด์ฉํ์.
void Update() {
for(int i = 0; i < mesh.vertices.Length; i++) {
float x, y, z;
x = mesh.vertices[i].x;
y = mesh.vertices[i].y;
z = mesh.vertices[i].z;
// ...
DoSomething(x, y, z);
}
}
Loop ์์ mesh.vertices.Length๋ฅผ ํธ์ถํ๊ฒ ๋๋ฉด Loop ๊ฐ 1ํ ๋์ํ ๋๋ง๋ค 4๊ฐ์ ์ ์ ๋ฐฐ์ด ๋ณต์ฌ๋ณธ์ ๋ถํ์ํ๊ฒ ๋ง๋ ๋ค. ํ ๋น์ .vertices ์์ฑ์ ์ ๊ทผํ ๋๋ง๋ค ์ด๋ฃจ์ด์ง๋ค.
void Update() {
var vertices = mesh.vertices;
for(int i = 0; i < vertices.Length; i++) {
float x, y, z;
x = vertices[i].x;
y = vertices[i].y;
z = vertices[i].z;
// ...
DoSomething(x, y, z);
}
}
Loop ๊ตฌ๋ฌธ ์ ์ vertices ๋ฅผ ์ ์ฅํ์ฌ single array ํ ๋น์ผ๋ก ๋ง๋ค ์ ์๋ค.
List<Vector3> m_vertices = new List<Vector3>();
void Update() {
mesh.GetVertices(m_vertices);
for(int i = 0; i < m_vertices.Length; i++) {
float x, y, z;
x = m_vertices[i].x;
y = m_vertices[i].y;
z = m_vertices[i].z;
// ...
DoSomething(x, y, z);
}
}
๊ฐ์ฅ ๋ฒ ์คํธ๋ ์์ ์ฝ๋ ์ด๋ค. Update ๊ตฌ๋ฌธ ๋ฐ์์ vertice ๋ค์ ๊ฐ๊ณ ์๋ ๊ฒ.
๊ทธ ์ธ ํ ๋น๋๋ API์ ํ ๋น๋์ง ์๋ API ๋ ์๋์ ๊ฐ๋ค. ๊ฐ๋ฅํ๋ฉด Non-allocating API ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ ๋ฐฉ๋ฒ์ด๋ค.
'๐ฎ Unity Study > Unity' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Unity Document Study] 2์ฃผ์ฐจ :: Asset Workflow (0) | 2024.05.11 |
---|---|
[Unity Document Study] 1์ฃผ์ฐจ :: Unity Analysis - Unity Profiler (0) | 2024.05.02 |
[Unity] Prefab Variant ํ๋ฆฌํน ์์ (0) | 2024.04.30 |
[Unity] Sound ๋ชจ๋ฐ์ผ ์ต์ ํ (0) | 2024.04.30 |
Unity Canvas :: Reference Pixels Per Unit (0) | 2024.04.16 |