2013-03-19 2 views
2

Я хочу уменьшить время выполнения кода. Глядя на некоторые результаты тестирования, я узнал, что GetHashCode() занимает 21,62% от моего времени выполнения.Как уменьшить сложность GetHashCode

Я также получил предупреждение:

Предупреждение 1 DA0010:.. * GetHashCode() = 7,63; Функции GetHashCode должны быть дешевыми и не выделять никакой памяти. Уменьшите сложность хеша функция кода, если это возможно.

фрагменты кода:

Мой GetHashCode() в поле Класс:

public override int GetHashCode() 
    { 
     int hash = 7; 
     hash = (hash * 13) + this.Coordinate.GetHashCode(); 
     return hash; 
    } 

Мой GetHashCode() в Координировать Класс:

public override int GetHashCode() 
    { 
     int hash = 17; 

     hash = (hash * 23) + this.Row.GetHashCode(); 
     hash = (hash * 23) + this.Column.GetHashCode(); 

     return hash; 
    } 

Edit: Row и Column - это только байтовые переменные. Я просто называю их свойство, которое возвращает байт в ГЭТ аксессору

Мой GetHashCode() в судоку Класс:

public override int GetHashCode() 
    { 
     int hash = 7; 

     hash = (hash * 5) + this.Grid.GetHashCode(); 

     return hash; 
    } 

Edit: Сетка просто многомерный массив типа: Field[,], я просто позвонить это свойство здесь, которое возвращает сетку Field [,] через доступ к нему.

Вопросы: Как я могу значительно уменьшить сложность моего GetHashCode() и увеличить его производительность? Почему производительность метода GetHashCode() низкая?

+2

Как выглядят методы 'GetHashCode' в' Row' и 'Column'? – siride

+0

Показать 'GetHashCode' для' Row' и 'Column'. –

+1

и 'GetHashCode' класса Grid? – Jehof

ответ

2

Я подозреваю, вы обнаружите, что GetHashCode не является вашей проблемой. Если вы тратите> 20% своего времени на GetHashCode, вы должны делать много поисков по словарю. Или вы используете хеш-код для чего-то, на что вы, вероятно, не должны его использовать.

GetHashCode может быть проявлением проблемы с производительностью, но это почти не является причиной.

+0

Да, я много ищущих словарей. Не следует ли в этом случае переопределить GetHashCode? – dylanmensaert

+0

О, да, вам нужно переопределить 'GetHashCode', если вы используете эти объекты в качестве словарных клавиш. Однако я подозреваю, что ваш алгоритм более высокого уровня неэффективен, что приводит к слишком большому количеству поисковых запросов в словарях. Я не могу сказать точно, конечно, не увидев ваш код, но это был мой опыт в прошлом. Я никогда не обнаружил, что «GetHashCode» является узким местом производительности. –

+0

Спасибо, я рассмотрю свой алгоритм и попытаюсь найти способ уменьшить количество поисков. – dylanmensaert

0

Похоже, проблема не в целостном добавлении, а в доступе к таким свойствам, как this.Coordinate, this.Grid, e.t.c.

Посмотрите, как получить доступ к ним, они могут выполнять дополнительную работу.

+0

Получить аксессуар очень просто. Просто возвращающ приватный datamember каждый раз. – dylanmensaert

2

Ваши расчеты просто добавляются к вашему хэш-коду. Только сочетание ваших hashcodes необходимо иметь более хэш-код, то просто добавив два значения:

//Field 
public override int GetHashCode() 
{ 
    return this.Coordinate.GetHashCode(); 
} 

//Coordinate 
public override int GetHashCode() 
{ 
    return this.Column.GetHashCode() * 17 + this.Row.GetHashCode(); 
}  

//Sudoku, I doubt if this is ever called... 
public override int GetHashCode() 
{ 
    return this.Grid.GetHashCode(); 
} 

Для выполнения это действительно зависит от того, как часто вы звоните GetHashCode (если вы сделаете какие-либо вычисления). Или, если вы храните их в каком-то словаре, проблема может быть несколькими значениями с одинаковым хешем, что сократит время доступа к объектам в словаре/хэш-таблице. Таким образом, ваша хэш-функция должна быть хорошим распределением для набора, который вы храните.

+0

+1, фактически отмечая легкую оптимизацию кода OP. – Adrian

1

Если в ваших классах не так много мутаторов, вы можете кэшировать хеш-код и просто вернуть кешированное значение из GetHashCode().(Даже если у вас много мутаторов, вы можете это сделать, но, вероятно, это будет намного менее эффективно, если объекты часто мутируются.)

Вам следует лениво оценить его. Вам нужно будет знать, когда он грязный, и его необходимо пересчитать. Вы можете сделать это легко, добавив поле bool isHashCodeDirty, которое инициализируется значением true при построении класса, а также каждым методом мутаторов.

Тогда в вашей реализации GetHashCode(), если значение isHashCodeDirty истинно, установите значение false и пересчитайте и верните хеш-код. Если это неверно, просто верните кешированное значение.

Здесь, конечно, вы должны быть осторожны с многопоточным движением. Я думаю, что добавление блокировки в GetHashCode() может сильно повлиять на производительность!

Идеально, конечно, иметь неизменные классы; то вы просто вычисляете хэш-код один раз в конструкторе, и он никогда не изменится после этого.

+0

Хеш-код никогда не может быть грязным (они должны оставаться неизменными по продолжительности жизни объектов), вы получите проблемы, когда у вас есть объекты в хэш-таблицах, когда изменяется хэш-код. – Peter

+0

@peer Ну, он должен быть постоянным в течение всего времени, когда это ключ Словаря, а не весь срок службы объекта (хотя они часто будут такими же или близкими к нему). Маловероятно, что хэш-код должен быть мутирован после его вычисления в первый раз. Будьте очень уверены, что знаете, что происходит, если это так. – Servy

+0

@peer: Да, вот почему я сказал, что идеал состоит в том, чтобы иметь непреложные классы! И мутирующий хеш-код - это красный флаг! –

Смежные вопросы