Level Streaming๊ณผ GC
๋ ๋ฒจ ์ธ๋ก๋ ์ GC ๋์, FlushStreamingLevel, ์ง์ฐ GC ์ ๋ต์ ๋ถ์ํฉ๋๋ค
๋ ๋ฒจ ์ธ๋ก๋์ GC
์๋ธ๋ ๋ฒจ์ด ์ธ๋ก๋๋ ๋ GC๊ฐ ๋์ํ๋ ๊ณผ์
๋ ๋ฒจ ์ธ๋ก๋ ์ GC ํ๋ฆ
UnloadStreamingLevel(SubLevel)
โ
โโโ SubLevel์ ๋ชจ๋ Actor์ Destroy() ํธ์ถ
โ โโโ ๊ฐ Actor: MarkAsGarbage()
โ
โโโ SubLevel์ ULevelStreaming ์ํ ๋ณ๊ฒฝ
โ โโโ Unloaded ์ํ๋ก ์ ํ
โ
โโโ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฆ์ GC ์คํ
โ โโโ CollectGarbage(GARBAGE_COLLECTION_KEEPFLAGS)
โ
โโโ ๊ฒฐ๊ณผ:
โโโ ์ธ๋ก๋๋ ๋ ๋ฒจ์ Actor๋ค ๋ฉ๋ชจ๋ฆฌ ํด์
โโโ ํด๋น ๋ ๋ฒจ ์ ์ฉ ์์
๋ค๋ ์ฐธ์กฐ ์์ผ๋ฉด GC
โโโ ์ด ๊ณผ์ ์์ GC ํ์น ๋ฐ์ ๊ฐ๋ฅ!
์๋ธ๋ ๋ฒจ ์ธ๋ก๋ ์งํ์ GC๋ Full GC๋ก ์คํ๋ ์ ์์ผ๋ฉฐ, ์์ฒ ๊ฐ์ Actor์ ์์ ์ ํ ๋ฒ์ ์ฒ๋ฆฌํ๋ฏ๋ก ์ฌ๊ฐํ ํ์น๋ฅผ ์ ๋ฐํฉ๋๋ค. ํนํ ์คํ์๋์์ ๋น๋ฒํ ๋ ๋ฒจ ์คํธ๋ฆฌ๋ฐ ์ ์ด ๋ฌธ์ ๊ฐ ๋๋๋ฌ์ง๋๋ค.
GC ํ์ด๋ฐ ์ ์ด ์ ๋ต
๋ ๋ฒจ ์คํธ๋ฆฌ๋ฐ๊ณผ GC ์คํ์ ๋ถ๋ฆฌํ๋ ๊ธฐ๋ฒ
์ง์ฐ GC ์ ๋ต
// ์ ๋ต 1: ๋ ๋ฒจ ์ธ๋ก๋ ์ GC ์ง์ฐ
// ์ธ๋ก๋ ์ ์ GC๋ฅผ ์ง์ฐ์ํค๊ณ , ์์ ํ ์์ ์ ์๋ ์คํ
GEngine->DelayGarbageCollection();
UnloadStreamLevel(SubLevelName);
// ... ๋ก๋ฉ ์คํฌ๋ฆฐ์ด๋ ์์ ํ ์์ ์์ ...
CollectGarbage(GARBAGE_COLLECTION_KEEPFLAGS);
// ์ ๋ต 2: Incrementalํ๊ฒ ์ฒ๋ฆฌ
// gc.TimeLimitSeconds๋ฅผ ์ค์ ํ๋ฉด ๋ ๋ฒจ ์ธ๋ก๋ ํ
// GC๊ฐ ์ฌ๋ฌ ํ๋ ์์ ๋ถ์ฐ๋จ
// ์ ๋ต 3: ๋ก๋ฉ ์คํฌ๋ฆฐ ์ค GC
void UMyGameInstance::OnLevelTransition()
{
// ๋ก๋ฉ ์คํฌ๋ฆฐ ํ์
ShowLoadingScreen();
// ์ด์ ๋ ๋ฒจ ์ธ๋ก๋
UnloadCurrentLevel();
// ๋ก๋ฉ ์คํฌ๋ฆฐ ์ค Full GC (ํ์น ๋ฌด๊ด)
CollectGarbage(GARBAGE_COLLECTION_KEEPFLAGS, true);
// ์ ๋ ๋ฒจ ๋ก๋
LoadNewLevel();
HideLoadingScreen();
}
World Partition๊ณผ GC
UE5 World Partition ์์คํ ์์์ GC ๊ณ ๋ ค์ฌํญ
World Partition์ GC ํน์ฑ
UE5์ World Partition์ ๋ ๋ฒจ์ ์ (Cell) ๋จ์๋ก ์๋ ๋ถํ ํ๊ณ ์คํธ๋ฆฌ๋ฐํฉ๋๋ค. ์ ํต์ ์ธ ์๋ธ๋ ๋ฒจ๋ณด๋ค ๋ ์ธ๋ถํ๋ ์คํธ๋ฆฌ๋ฐ์ด ๊ฐ๋ฅํ๋ฉฐ, GC ๋์๋ ๋ฌ๋ผ์ง๋๋ค.
// World Partition ์
์ธ๋ก๋ ์
1. ์
๋ด Actor๋ค์ด ๋นํ์ฑํ/ํ๊ดด
2. ์์ ๋จ์(์
)๋ก ์ธ๋ก๋๋๋ฏ๋ก GC ๋ถํ ๋ถ์ฐ
3. Data Layer๋ณ ๋
๋ฆฝ์ ์คํธ๋ฆฌ๋ฐ ๊ฐ๋ฅ
// ๊ด๋ จ ์ค์
[/Script/Engine.WorldPartition]
RuntimeHashClass=RuntimeSpatialHash
bEnableStreaming=True
LoadingRange=25600 // ๋ก๋ฉ ๋ฒ์ (cm)
// GC ์ต์ ํ ํฌ์ธํธ:
// - ์
ํฌ๊ธฐ๋ฅผ ์ ์ ํ ์ค์ (๋๋ฌด ์์ผ๋ฉด ๋น๋ฒํ ์คํธ๋ฆฌ๋ฐ)
// - HLOD๋ฅผ ํ์ฉํ์ฌ ์๊ฑฐ๋ฆฌ ๊ฐ์ฒด ์ ๊ฐ์
// - One File Per Actor๋ก ์ธ๋ถํ๋ ๋ก๋ฉ
World Partition์ ์ ๋จ์ ์คํธ๋ฆฌ๋ฐ์ผ๋ก GC ๋ถํ๊ฐ ์์ฐ์ค๋ฝ๊ฒ ๋ถ์ฐ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ํ๋ ์ด์ด๊ฐ ๋น ๋ฅด๊ฒ ์ด๋ํ๋ฉด ๋ง์ ์ ์ด ๋์์ ์ธ๋ก๋๋์ด GC ์คํ์ดํฌ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ ์๋์ ๋ง์ถฐ LoadingRange๋ฅผ ์กฐ์ ํ์ธ์.
์์ ์ฐธ์กฐ์ ๋ ๋ฒจ GC
๋ ๋ฒจ ๊ฐ ์์ ์ฐธ์กฐ๊ฐ GC์ ๋ฏธ์น๋ ์ํฅ
ํฌ๋ก์ค ๋ ๋ฒจ ์ฐธ์กฐ ๋ฌธ์
// ๋ฌธ์ : ์๋ธ๋ ๋ฒจ B๊ฐ ์๋ธ๋ ๋ฒจ A์ ์์
์ ์ฐธ์กฐ
SubLevel_A: SM_LargeBuilding (100MB)
SubLevel_B: Actor๊ฐ SM_LargeBuilding์ ์ฐธ์กฐ
// SubLevel_A๋ฅผ ์ธ๋ก๋ํด๋
// SubLevel_B์ ์ฐธ์กฐ๋ก SM_LargeBuilding์ด GC๋์ง ์์!
// โ 100MB๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์๋ฅ
// ํด๊ฒฐ ๋ฐฉ๋ฒ:
1. TSoftObjectPtr ์ฌ์ฉ
โ ์ฝํ ์ฐธ์กฐ์ด๋ฏ๋ก ์์
GC ๊ฐ๋ฅ
2. ๊ณต์ ์์
๋ ๋ฒจ ๋ถ๋ฆฌ
โ SharedAssets ๋ ๋ฒจ์ ๊ณตํต ์์
๋ฐฐ์น
3. ์์
๋งค๋์ ํ์ฉ
โ Primary Asset์ผ๋ก ๋ช
์์ ๋ก๋/์ธ๋ก๋
ํต์ฌ ์์ฝ
- ๋ ๋ฒจ ์ธ๋ก๋ ์งํ์ Full GC๋ ์ฌ๊ฐํ ํ์น๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค
- DelayGarbageCollection()๊ณผ ๋ก๋ฉ ์คํฌ๋ฆฐ์ ํ์ฉํ์ฌ GC ํ์ด๋ฐ์ ์ ์ดํฉ๋๋ค
- World Partition์ ์ ๋จ์ ์คํธ๋ฆฌ๋ฐ์ผ๋ก GC ๋ถํ๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ๋ถ์ฐํฉ๋๋ค
- ํฌ๋ก์ค ๋ ๋ฒจ ์์ ์ฐธ์กฐ๋ ์ธ๋ก๋ ํ์๋ ๋ฉ๋ชจ๋ฆฌ ์๋ฅ๋ฅผ ์ ๋ฐํ๋ฏ๋ก TSoftObjectPtr๋ฅผ ํ์ฉํฉ๋๋ค
- ์คํ์๋์์๋ LoadingRange์ ์ ํฌ๊ธฐ๋ฅผ ์ ์ ํ ์กฐ์ ํ์ฌ GC ์คํ์ดํฌ๋ฅผ ๋ฐฉ์งํฉ๋๋ค
๋์ ๊ณผ์
๋ฐฐ์ด ๋ด์ฉ์ ์ง์ ์ค์ตํด๋ณด์ธ์
World Partition ๋๋ Level Streaming Volume์ผ๋ก ์๋ธ๋ ๋ฒจ์ ๋ก๋/์ธ๋ก๋ํ๋ฉด์ stat gc์ stat memory์ ๋ณํ๋ฅผ ๊ด์ฐฐํ์ธ์. ๋ ๋ฒจ ์ธ๋ก๋ ํ GC๊ฐ ์๋ฃ๋๊ธฐ๊น์ง์ ์๊ฐ๊ณผ ํด์ ๋๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ธก์ ํ์ธ์.
UGameplayStatics::FlushLevelStreaming()๊ณผ ForceGarbageCollection()์ ์กฐํฉ์ผ๋ก ๋ ๋ฒจ ์ ํ ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์์ ํ ์ ๋ฆฌํ๋ ํจํด์ ๊ตฌํํ์ธ์. ๋ก๋ฉ ํ๋ฉด ์ค์ GC๋ฅผ ์ง์ค ์คํํ์ฌ ๊ฒ์ํ๋ ์ด ์ค ํ์น๋ฅผ ๋ฐฉ์งํ์ธ์.
World Partition ๊ธฐ๋ฐ ์คํ์๋์์ ์ ๋ก๋/์ธ๋ก๋์ ๋ฐ๋ฅธ GC ๋ถํ๋ฅผ ์ต์ ํํ์ธ์. ํ๋ฆฌ๋ก๋ฉ, ์์ ํด๋ฌ์คํฐ๋ง, ์ ์ง์ ์ธ๋ก๋, GC ํ์ด๋ฐ ์กฐ์ ์ ์กฐํฉํ์ฌ ์ฌ๋ฆฌ์ค ์คํธ๋ฆฌ๋ฐ ํ๊ฒฝ์์ ํ์น ์๋ GC๋ฅผ ๊ตฌํํ์ธ์.