Непонятное с GetHashCode
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.07.10 14:40
Оценка:
Протестировал кое какие нюансы с GetHashCode с целью оптимизации участка, где много обращений к Dictionary — получение значения по ключу, добавление элементов по ключу и тд.
Получилось чтото непонятное.

Release

Test20 GetHashCode default
3,062461
Test21 GetHashCode from string
0,540457
Test22 GetHashCode overrided, fixed value
0,4687002
Test23 GetHashCode inherited default
2,747097
Test24 GetHashCode cashed default
0,4954112


Единицы измерения не важны, получены с пом. QueryPerformanceCounter, кол-во запусков контрольных участков >1000000

По результатам выходит что дефолтный метод работает медленнее чем он же унаследованый
Унаследованый кешированый работает намного быстрее, следовательно дефолтный ничего не кеширует и вычисляет значение постоянно

Вопрос 1 — почему дефолтный работает медленно, если коде ротора вроде как есть кеширование значения в дефолтной реализации ?

Вопрос 2 — почему метод работает примерно так же как и с кешированием, хотя в коде для строки нет никакого кеширования ?.


P.S. 4.0 дефотный работает чуть быстрее чем 3.5, процентов на 10

Тесты, классы и вычисление хешкода для строки

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public override unsafe int GetHashCode()
{
    fixed (char* str = ((char*) this))
    {
        char* chPtr = str;
        int num = 0x15051505;
        int num2 = num;
        int* numPtr = (int*) chPtr;
        for (int i = this.Length; i > 0; i -= 4)
        {
            num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
            if (i <= 2)
            {
                break;
            }
            num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
            numPtr += 2;
        }
        return (num + (num2 * 0x5d588b65));
    }
}


        [NamedTest("GetHashCode default")]
        private static void Test20()
        {
            object o = new HashCodeWrapper(new object());

            for (int j = 0; j < Count; j++)
            {
                i ^= o.GetHashCode();
            }
        }

        [NamedTest("GetHashCode from string")]
        private static void Test21()
        {
            object s = new HashCodeWrapper("345");



            for (int j = 0; j < Count; j++)
            {
                i ^= s.GetHashCode();
            }
        }

        [NamedTest("GetHashCode overrided, fixed value")]
        private static void Test22()
        {
            object s = new HashCodeWrapper(new Suxx2(123));

            for (int j = 0; j < Count; j++)
            {
                i ^= s.GetHashCode();
            }
        }

        [NamedTest("GetHashCode inherited default")]
        private static void Test23()
        {
            object s = new HashCodeWrapper(new Suxx());

            for (int j = 0; j < Count; j++)
            {
                i ^= s.GetHashCode();
            }
        }

        [NamedTest("GetHashCode cashed default")]
        private static void Test24()
        {
            object s = new HashCodeWrapper(new Suxx3());

            for (int j = 0; j < Count; j++)
            {
                i ^= s.GetHashCode();
            }
        }


    class Suxx
    {
        private RectangleF rectf;
        private readonly int _hashCode;
    }

    class Suxx3
    {
        private RectangleF rectf;
        private int _hashCode = 0;

        public override int GetHashCode()
        {
            if (_hashCode == 0)
                _hashCode = base.GetHashCode();

            return _hashCode;
        }
    }
    class Suxx2
    {
        private RectangleF rectf;
        private readonly int _hashCode;

        public Suxx2(int hashCode)
        {
            _hashCode = hashCode;
        }

        public override int GetHashCode()
        {
            return _hashCode;
        }
    }

    class SuxxD
    {
        private RectangleD rectd;
    }

    struct RectangleD
    {
        public double X;
        public double Y;
        public double Width;
        public double Height;
    }

    class HashCodeWrapper
    {
        private readonly object _o;

        public HashCodeWrapper(object o)
        {
            _o = o;
        }

        public override int GetHashCode()
        {
            return _o.GetHashCode();
        }
    }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.