300x250

이테스트를 한 이유는 코루틴 최적화를 알아보던 도중 WaitForSeconds(seconds)를 캐싱하려면 딕셔너리에 seconds를 넣어두고 기존에 사용한 적이 있으면 캐싱한 WaitForSeconds를 반환하고 사용한 적이 없으면 딕셔너리에 해당 seconds를 넣어서 캐싱하는 기법을 사용한다고 해요.

 

그때는 맞고 지금은 틀리다 - 제네릭 컬렉션도 박싱이 발생할 수 있다 | Overworks’ lab in GitHub

 

이때 사용한 적이 있는지를 확인하기 위해 딕셔너리에 TryGetValue를 사용하는 과정 중 박싱이 발생할 수 있다고 하여 IEqualityComparer 인터페이스를 새로 구현하여 딕셔너리에 비교 연산자로 넣어줘야 한다고 해서 object 형식이 아닌 비교하려는 자료형을 선언하여 박싱이 일어나지 않게 해야 한다고 하는데 이 부분이 이해가 가지 않아서 테스트를 해봤어요.

 

 

C# 도큐먼트를 봤을 때는 object가 아닌 제네릭형식 TKey를 받아서 하고 있기 때문에 박싱이 일어나지 않을까 생각했어요.

 

제네릭 컬렉션도 방식이 발생할 수 있다 글에서 테스트한 프로파일링 결과예요 해당결과를 보면

DefaultComparer를 사용할 때 가비지 컬렉션이 발생하는것을 알 수 있어요.

 

저도 동일한 코드를 작성해서 테스트 해봤어요.

using System.Collections.Generic;
using UnityEngine;

public class StructTest : MonoBehaviour
{
    public struct Struct
    {
        public int value;

        public Struct(int value)
        {
            this.value = value;
        }
    }

    private Dictionary<Struct, string> structDic = new Dictionary<Struct, string>();

    private void Start()
    {
        for (int i = 0; i < 5; ++i)
        {
            structDic.Add(new Struct(i), i.ToString());
        }
    }


    void Update()
    {
        string str;
        for (int i = 0; i < 5; ++i)
        {
            structDic.TryGetValue(new Struct(i), out str);
        }
    }
}

 

using System.Collections.Generic;
using UnityEngine;

public class IntTest : MonoBehaviour
{
    private Dictionary<int, string> intDic = new Dictionary<int, string>();

    void Start()
    {
        for (int i = 0; i < 5; ++i)
        {
            intDic.Add(i, i.ToString());
        }
    }

    void Update()
    {
        string str;
        for (int i = 0; i < 5; ++i)
        {
            intDic.TryGetValue(i, out str);
        }
    }
}

 

using System.Collections.Generic;
using UnityEngine;

public class EnumTest : MonoBehaviour
{
    public enum Enums
    {
        Enums0,
        Enums1,
        Enums2,
        Enums3,
        Enums4,
    }

    Dictionary<Enums, string> enumDic = new Dictionary<Enums, string>();

    void Start()
    {
        for (int i = 0; i < 5; ++i)
        {
            enumDic.Add((Enums)i, i.ToString());
        }
    }

    void Update()
    {
        string str;
        for (int i = 0; i < 5; ++i)
        {
            enumDic.TryGetValue((Enums)i, out str);
        }
    }
}

 

저 또한 가비지가 생기고 있으나 Enum에선 생기지 않고 있는 것을 볼 수 있고 DefaultComparer는 확인할 수 없었어요. 다만 이때 생기는 가비지 또한 박싱때문에 생긴 다기보단 

비교를 할 때 new 키워드를 사용해서 인스턴스를 새로 만들고 있어서 가비지가 생기는 게 아닌가란 생각이 들었어요. 아마 위에 테스트 당시보다 유니티 버전이 오르고 C# 버전도 올라서 그런 게 아닐까 조심스럽게 예상해 봐요.

이제 코루틴 최적화도 테스트해 볼 건데 제 예상엔 IEqualityComparer는 구현 안 해도 캐싱하는데 문제가 없지 않을까 미리 예상해 봐요.

 

저는 유니티 버전 2021.3.5f1, .NET Standard 2.1, Visual Studio 2019 환경에서 테스트했어요.

 

참고자료:

그때는 맞고 지금은 틀리다 - 제네릭 컬렉션도 박싱이 발생할 수 있다 | Overworks’ lab in GitHub

 

 

300x250