Unity ECS 메모리

Changhoony·2022년 11월 27일
1

Unity ECS

목록 보기
1/1

출처 : 필독

들어가며

구조체의 크기는, 구조체 내부의 변수들의 정렬에 의해 가변적일 수 있다.

구조체 내부, 정렬의 중요성

다음의 메모리 사이즈와 메모리 배열을 살펴보자.

public struct TestA
{
	public int itemA;
    public bool itemB;
    public int itemC;
    public bool itemD;
}

public struct TestB
{
	public int itemA;
    public int itemC;
    public bool itemB;
    public bool itemD;
}

결과 도출 코드

private void Start()
{
  // TestA의 메모리 체크
  Debug.Log($"UnsafeUtility.AlignOf<TestA>() :: {UnsafeUtility.AlignOf<TestA>()}");
  Debug.Log($"UnsafeUtility.SizeOf<TestA>() :: {UnsafeUtility.SizeOf<TestA>()}");
  
  // TestB의 메모리 체크
   Debug.Log($"UnsafeUtility.AlignOf<TestB>() :: {UnsafeUtility.AlignOf<TestB>()}");
  Debug.Log($"UnsafeUtility.SizeOf<TestB>() :: {UnsafeUtility.SizeOf<TestB>()}");
}

결과

  • TestA 구조체
    Align : 4 byte

    Size : 16 byte

  • TestB 구조체
    Align : 4 byte
    Size : 12 byte

무려 25%의 효과를 얻을 수 있다.

( 이에 대한 자세한 설명은 출처를 참고하였다. )

우선 구조체 TestA의 정렬은

1 itemA | itemA | itemA | itemA
2 itemB | - | - | -
3 itemC | itemC | itemC | itemC
4 itemD | - | - | -

와 같고

TestB의 메모리 정렬은

1 itemA | itemA | itemA | itemA
2 itemC | itemC | itemC | itemC
3 itemB | itemD | - | -

와 같다.

중첩 구조체 지양

다음의 메모리 사이즈와 메모리 배열을 살펴보자.

// 중첩용 구조체
public struct TestA
{
	public bool a;
    public long b;
    public bool c;
}
// 중첩된 구조체
public struct TestB
{
	public TestA a;
    public bool d;
    public int e;
}
// 중첩 해제후 무작위 정렬한 구조체
public struct TestC
{
	public bool a;
    public long b;
    public bool c;
    public bool d;
    public int e;
}
// 중첩 해제후 정렬한 구조체 
public struct TestD
{
    public long b;
	public bool a;
    public bool c;
    public bool d;
    public int e;
}

결과

  • TestA 구조체
    Align : 8 byte
    Size : 24 byte | 정렬시 Size : 16byte

  • TestB 구조체
    Align : 8 byte
    Size : 32 byte

  • TestC 구조체 : TestB 구조체 대비 25% 절감
    Align : 8 byte
    Size : 24 byte

  • TestD 구조체 : TestB 구조체 대비 50% 절감
    Align : 8 byte
    Size : 16 byte

메모리 배열

  • TestA ( Align : 8 / Size : 24 )

1 a | - | - | - | - | - | - | -
2 b | b | b | b | b | b | b | b
3 c | - | - | - | - | - | - | -

TestB , C , D는 다음과 같다.

  • TestB

1 a | - | - | - | - | - | - | -
2 b | b | b | b | b | b | b | b
3 c | - | - | - | - | - | - | -
4 e | e | e | e | d | - | - | -

  • TestC

1 a | - | - | - | - | - | - | -
2 b | b | b | b | b | b | b | b
3 e | e | e | e | c | d | - | -

  • TestD

1 b | b | b | b | b | b | b | b
2 e | e | e | e | c | d | a | -

열거형도 주의하자.

public enum TestEnum
{
 	itemA,
    itemB,
    ...
}

만약 이런 식으로 선언한다면, 이 enum은 int 형을 따라간다. 고로 4byte의 크기를 지니는데, ushort나 byte로 정의하면 2byte 내지 1byte로 처리가 가능하다.

public enum TestEnum : byte
{
 	itemA,
    itemB,
    ...
}

참고

public struct EmptyStruct
{

}
public struct EnumeratorStruct
{
	public IEnumerator routine;
}
  • 빈 구조체 ( ECS 태그 )의 경우
    Align : 1byte
    Size : 1byte
  • 열거형(IEnumerator) 구조체의 경우
    Align : 8byte
    Size : 8byte
public struct NativeArrayStruct
{
	public NativeArray<T> array;
}
public struct NativeListStruct
{
	public NativeList<T> list;
}
public struct NativeQueueStruct
{
	public NativeList<T> list;
}
public struct NativeListStruct
{
	public NativeList<T> list;
}
public struct NativeHashMapStruct
{
	public NativeHasMap<K,V> map;
}
public struct NativeTextStruct
{
	public NativeText text;
}
public struct NativeParallelHashMap
{
	public NativeParallelHashMap<K,V> parallelMap;
}
public struct BlobString
{
	public BlobString str;
}
  • NativeArray의 경우
    Align : 8byte
    Size : 48byte
  • NativeList의 경우
    Align : 8byte
    Size : 32byte
  • NativeQueue의 경우
    Align : 8byte
    Size : 40byte
  • NativeHashMap의 경우
    Align : 8byte
    Size : 24byte
  • NativeText의 경우
    Align : 8byte
    Size : 24byte
  • NativeParallelHashMap 경우
    Align : 8byte
    Size : 32byte
  • BlobString 경우
    Align : 4byte
    Size : 8byte
profile
Unity 개발

0개의 댓글