코드 짤때는 GC호출을 최소화해야함
그러려면 가비지를 만드는일을 최소화해야하는데
그 중 Dictionary의 key를 Enum으로 쓰는 경우를 테스트 해봄
* Init
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
enum TestEnum
{
A,
}
public class DictionaryEnumTest : MonoBehaviour
{
Dictionary<TestEnum, string> testEnumDic;
Dictionary<int, string> testIntDic;
// Use this for initialization
void Start()
{
InitEnumDic();
InitIntDic();
}
void InitEnumDic()
{
testEnumDic = new Dictionary<TestEnum, string>();
}
void InitIntDic()
{
testIntDic = new Dictionary<int, string>();
}
}
위 코드로 테스트한 프로파일러 결과임
빨간색 칠해둔것을 보면 Enum을 Key로 한 Dictionary가 GC Alloc 0.2KB 더 많이함
양이 많지는 않음(빈번하면 안좋음)
* Add
아까 생성한 두 Dictionary에 각각 값을 넣어봤음
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
enum TestEnum
{
A,
}
public class DictionaryEnumTest : MonoBehaviour
{
Dictionary<TestEnum, string> testEnumDic;
Dictionary<int, string> testIntDic;
// Use this for initialization
void Start()
{
InitEnumDic();
InitIntDic();
AddEnumDic();
AddIntDic();
}
void InitEnumDic()
{
testEnumDic = new Dictionary<TestEnum, string>();
}
void InitIntDic()
{
testIntDic = new Dictionary<int, string>();
}
void AddEnumDic()
{
testEnumDic.Add(TestEnum.A, "A");
}
void AddIntDic()
{
testIntDic.Add(1, "A");
}
}
20B를 생성했음..
Dictionary에 값이 많이 들어간다 생각하면 개손해임
* TryGetValue
가장 빈번할것으로 예상되는 값 찾기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
enum TestEnum
{
A,
}
public class DictionaryEnumTest : MonoBehaviour
{
Dictionary<TestEnum, string> testEnumDic;
Dictionary<int, string> testIntDic;
// Use this for initialization
void Start()
{
InitEnumDic();
InitIntDic();
AddEnumDic();
AddIntDic();
GetValueEnumDic();
GetValueIntDic();
}
void InitEnumDic()
{
testEnumDic = new Dictionary<TestEnum, string>();
}
void InitIntDic()
{
testIntDic = new Dictionary<int, string>();
}
void AddEnumDic()
{
testEnumDic.Add(TestEnum.A, "A");
}
void AddIntDic()
{
testIntDic.Add(1, "A");
}
void GetValueEnumDic()
{
string result;
testEnumDic.TryGetValue(TestEnum.A, out result);
}
void GetValueIntDic()
{
string result;
testIntDic.TryGetValue(1, out result);
}
}
Key가 int인거는 0생성했는데
enum인거는 1번찾는데 60B 생성함... 핵손해
장난삼아 10만번 돌려봄
게임마다 다르겠지만 10만번을 찾을일이 게임에서 많지는 않을 것 같은데 아무튼 5.7MB나 생성함
* 해결책
https://stackoverflow.com/questions/26280788/dictionary-enum-key-performance
위 링크를 보고 함
저 중에서 가장 쉬워보이는 1번 솔루션을 적용해봄
첫번째 프로파일러 스크린샷인데 저걸 열어보면 EqualityComparer라는애가 있음
키를 비교할 때 enum이기때문에 비교할 때 Boxing UnBoxing하는데 비용이 크다고 함
그래서 비교하는애를 Dictionary 생성할 때 넣어주는거임
public struct MyEnumCOmparer : IEqualityComparer<MyEnum>
{
public bool Equals(MyEnum x, MyEnum y)
{
return x == y;
}
public int GetHashCode(MyEnum obj)
{
// you need to do some thinking here,
return (int)obj;
}
}
new Dictionary<MyEnum, int>(new MyEnumComparer());
이 코드를 나의 테스트 코드에 맞게 바꾸고 테스트 함
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum TestEnum
{
A,
}
public struct TestEnumComparer : IEqualityComparer<TestEnum>
{
public bool Equals(TestEnum x, TestEnum y)
{
return x == y;
}
public int GetHashCode(TestEnum obj)
{
return (int)obj;
}
}
public class DictionaryEnumTest : MonoBehaviour
{
Dictionary<TestEnum, string> testEnumDic;
// Use this for initialization
void Start()
{
InitEnumDic();
AddEnumDic();
GetValueEnumDic();
}
void InitEnumDic()
{
testEnumDic = new Dictionary<TestEnum, string>(new TestEnumComparer());
}
void AddEnumDic()
{
testEnumDic.Add(TestEnum.A, "A");
}
void GetValueEnumDic()
{
string result;
for(int i=0;i<100000;i++)
testEnumDic.TryGetValue(TestEnum.A, out result);
}
}
10만번 Get할때 가비지 한개도 안생기고 Add할때도 사라짐
개이득
생성할 때도 없애기 위해서 Dictionary key값을 int로 바꾸는거는 너무 가독성면에서나 작업량에서나 손해고
Key는 enum으로 쓰면서 위 방법을 사용하면 어느정도 쉽고 빠르게 해결 가능