Есть ли ограничение на количество записей в словаре <>? - PullRequest
9 голосов
/ 11 августа 2010

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

Я создал свою собственную структуру переменных. Я думал о создании «Словаря» в начале моего приложения, и просто загружаю все мои файлы до запуска игры.

Меня интересует производительность: будет ли словарь с таким количеством записей замедлять работу моего приложения? Будет ли большой словарь замедлять работу «TryGetValue» и «ContainsKey»?

спасибо за совет!

Ответы [ 8 ]

14 голосов
/ 11 августа 2010

TryGetValue и ContainsKey должны быть довольно быстрыми при таком размере, если ключ имеет хорошо распределенные хэши.

Словарь имеет индексируемое количество «сегментов».Когда он добавляет или ищет значение по ключу, он принимает значение, возвращаемое GetHashCode (), снова хэширует его, чтобы оно было меньше количества сегментов (обычно что-то простое, например, по модулю, но реализация не определена),и посмотрите в соответствующее ведро.

В настоящее время ведро будет иметь ноль или более предметов.Словарь сравнивает каждый элемент с ключом, используя .Equals ().

Первый бит поиска правильного сегмента будет в постоянном времени O (1).Второй бит сравнения ключа с ключами в корзине будет происходить за линейное время O (n), где n относится только к количеству элементов в этой корзине, а не во всей коллекции.

Обычнов каждом сегменте должно быть очень мало элементов (количество сегментов будет расти, чтобы попытаться сохранить это положение), поэтому операция по существу постоянна.

Если, однако, ваши хэш-коды плохо реализованы, будетмного ключей в одном ведре.Временная сложность будет становиться все ближе и ближе к O (n), что можно увидеть, экспериментируя с объектом с намеренно плохим GetHashCode, который просто возвращает 0 каждый раз.В худшем случае он хуже, чем List, поскольку List также является O (n), но у Dictionary есть дополнительные накладные расходы.

Значит ли это, что вам следует беспокоиться?Нет, даже относительно наивные методы хеширования должны давать относительно хорошие результаты.Если вы используете строковый ключ, то он, вероятно, будет более чем достаточно хорош.Если вы используете простой встроенный тип, то тем более.

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

Скорее всего, 3000 - ничто, все будет хорошо.

12 голосов
/ 11 августа 2010

3000 записей для Dictionary<>. Это не будет источником замедления.

Считывание 3000 различных файлов в память при запуске, с другой стороны, будет медленным. Вы будете гораздо лучше читать файлы в память только тогда, когда они необходимы, но впоследствии будете хранить их в памяти для последующих обращений.

7 голосов
/ 11 августа 2010

Нет, не будет. Он будет занимать память, но TryGetValue и ContainKey должны быть довольно быстрыми, так как словарь является хеш-таблицей, а доступ к элементам по ключу постоянен и не зависит от количества элементов.

4 голосов
/ 11 августа 2010

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

Подробнее см. http://en.wikipedia.org/wiki/Hashtable#Performance_analysis.

3 голосов
/ 11 августа 2010

Есть предел, но 3000 рядом нет.Dictionary<> использует Object.GetHashCode() для организации своих ключей, что возвращает int.Поэтому вы можете хранить максимум 2^32 (4 294 967 296) ключей, прежде чем произойдет столкновение.Однако из-за того, что хэш-коды .Net обычно рассчитываются, при приближении к этому магическому числу, вероятно, будет много коллизий.

Добавление большего количества ключей не замедлит TryGetValue и ContainsKey - ониO(1) операций.

1 голос
/ 11 августа 2010

Как и в большинстве случаев с компьютерами (и особенно с производительностью), «Это зависит (тм)»

Все зависит от реализации словаря.

Это может быть сделано в виде двоичного дерева, в этом случае поиск должен быть O (log2 N), что означает, что время поиска увеличивается медленно с увеличением размера словаря.

Это можно сделать в виде хеш-таблицы, которая, по идее, равна O (1), что означает, что поиск всегда будет занимать одинаковое количество времени, независимо от размера словаря, но это теория и зависит на количество сегментов и качество хеш-кода. Если многие элементы оказываются в одном и том же сегменте, требуя линейного поиска, они значительно замедляются по мере увеличения словаря.

Однако словарь должен вырасти за пределы 3000 на несколько порядков, прежде чем вы заметите заметную разницу.

1 голос
/ 11 августа 2010

Узким местом будет не производительность словаря, а чтение 3000 файлов.

1 голос
/ 11 августа 2010

В словарях .NET используется схема поиска в хеш-таблице, поэтому добавление записей практически не влияет на производительность поиска. Единственная проблема, которую вы будете иметь, может быть использование памяти. Словарь из 3000 элементов потребляет примерно в 3000 раз больше памяти, используемой ключом, плюс типы значений. Если это просто простая структура без огромных двоичных двоичных объектов, 3000 просто крошечный.

...