Solution to GC problem caused by unpacking / boxing operation in Unity

In the development of Unity C, Enum or structure are often used as the key of Dictionary or the element of List, namely:

List<EnumType>,Dictionary<EnumType, ValueType>,List<StructType>,Dictionary<StructType, ValueType>.

During the ContainsKey() or [] operations of the List, Dictionary, Equals() and GetHasCode() will be called to box Enum or Struct types, causing GC problems.

Solution:

1. Struct ure, override GetHasCode() and implement iequatable < T >. For example:

/// <summary>
        /// sizeof(KeyStruct) = 12B
        /// test Dictionary Of Contains()and[]
        /// 1.No override GetHashCode()And Realization IEquatable<T>
        ///     Contains():84B
        ///     []:84B
        /// 2.Implementation only IEquatable<T>
        ///     Contains():28B
        ///     []:28B
        ///     []:84B
        /// 3.only override GetHashCode()
        ///     Contains():56B
        ///     []:56B
        /// 4.override GetHashCode()And Realization IEquatable<T>
        ///     Contains():0
        ///     []:0
        /// </summary>
        struct KeyStruct : IEquatable<KeyStruct>
        {
            public int a;
            public int b;
            public int c;

            public KeyStruct(int a, int b, int c)
            {
                this.a = a;
                this.b = b;
                this.c = c;
            }

            public override int GetHashCode()
            {
                return this.a * 100 + this.b * 10 + this.c;
            }

            public bool Equals(KeyStruct obj)
            {
                return this.a == obj.a && this.b == obj.b && this.c == obj.c;
            }
        }

2. Enum type requires other methods because it cannot override and implement interfaces.

When used as a Dictionary key, a special comparator can be defined for Enum, as follows:

        enum KeyEnum
        {
            K1,
            K2,
            K3,
            K4,
        }

        struct KeyEnumComparer : IEqualityComparer<KeyEnum>
        {
            public bool Equals(KeyEnum x, KeyEnum y)
            {
                return x == y;
            }

            public int GetHashCode(KeyEnum obj)
            {
                // you need to do some thinking here,
                return (int)obj;
            }
        }

        Dictionary<KeyEnum, KeyEnum> enumDict2 = new Dictionary<KeyEnum, KeyEnum>(new KeyEnumComparer())
        {
            {KeyEnum.K1,KeyEnum.K1},
            {KeyEnum.K2,KeyEnum.K1},
            {KeyEnum.K3,KeyEnum.K1},
            {KeyEnum.K4,KeyEnum.K1}
        };

Enum is used in List. Since a custom comparer cannot be passed in the constructor, it is recommended to use List. Exists (E = > e = = keyenum. K1) instead of List.Contains(KeyEnum.K1) to avoid calls to Equals().

Tags: C# Unity

Posted on Wed, 01 Apr 2020 13:57:54 -0700 by glassroof