2014-09-07 2 views
1

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

Так что сейчас у меня есть что-то вроде этого:

private Dictionary<string, string> Data; 

public string GetValue(string key) // This gets hit very often 
{ 
    string value; 

     if (this.Data.TryGetValue(key, out value)) 
     { 
      return value; 
     } 

    ... 
} 

Есть ли более оптимальный способ сделать это?

+0

Это очень быстрый способ, как он не будет перебирать весь список, а просто попытается получить доступ к ключу напрямую и вернуть результат или null – Prix

+0

@Devha, что вы подразумеваете под «лучшим способом»? быстрый? удобства разработчика? – user3165438

+0

@ пользователь3165438 лучший способ = самый быстрый способ, в этом случае :) – devha

ответ

1

Использование TryGetValue - довольно оптимальный способ возврата предмета, поэтому на этом фронте вы не можете улучшить его. Однако, если это не вызывает узкого места на данный момент, я бы не стал слишком беспокоиться о попытке оптимизировать TryGetValue.

Одна вещь, которую вы можете сделать, но не указана в коде, поэтому я не знаю, являетесь ли вы, заключается в создании объекта Dictionary с предполагаемой пропускной способностью. Поскольку вы, похоже, знаете приблизительное количество элементов, которые ожидаются, создание словаря с этой емкостью улучшит производительность, поскольку это уменьшит количество раз, когда .NET должен изменить размер словаря.

От MSDN:

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

+0

Thank keyboardP. В настоящее время добавление элементов не является новой бутылочкой, так как Dictionaty заполняется только один раз в жизненном цикле приложения. Мне просто интересно, есть ли лучшая коллекция, чем словарь, которые лучше подходят для интенсивных запросов? – devha

+0

Я думаю, что «Словарь» выглядит как хорошая структура для использования здесь, поэтому, если у вас действительно проблемы с производительностью при поиске, вы можете либо использовать несколько словарей легкой базы данных (хотя я был бы удивлен, если 2500 элементов вызывая проблему, но я предполагаю, что это будет зависеть от типа проекта, над которым вы работаете). – keyboardP

2

Что вы имеете, очень эффективно. Единственный способ улучшить производительность, о которой я могу думать, - использовать int в качестве словарного ключа, а не string. Вам нужно будет выполнить тесты производительности, чтобы увидеть, насколько это имеет значение в вашем случае использования - это может быть или не быть значительным.

И я бы использовал перечисление для хранения настроек для удобства. Конечно, это предполагает, что у вас есть известный набор настроек.

private Dictionary<int, string> Data; 

public string GetValue(MyAppSettingsEnum key) 
{ 
    string value; 

    if (this.Data.TryGetValue((int)key, out value)) 
    { 
     return value; 
    } 

    ... 
} 

Обратите внимание, что я не использовать перечисление непосредственно в качестве словаря ключ, так как это более эффективно использовать int в качестве ключа. Подробнее об этом выпуске here.

1

Единственный более быстрый способ - использовать массив, если ваши ключи являются int и имеют короткий диапазон.

+0

Это не дает ответа на вопрос. Чтобы критиковать или просить разъяснения у автора, оставьте комментарий ниже их сообщения. –

+0

Использование массива является более оптимальным способом для того, чтобы выяснить, были ли выполнены некоторые ограничения. – brz

0

Как вы можете видеть из исходного кода System.Collections.Generic.Dictionary (доступен в http://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs) наиболее часто используемого кода, в вашем случае

private int FindEntry(TKey key) { 
    if(key == null) { 
     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); 
    } 

    if (buckets != null) { 
     int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; 
     for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) { 
      if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i; 
     } 
    } 
    return -1; 
} 

, как вы можете видеть, далее поиск быстро, если comparer.GetHashCode быстро и производит хорошее распределение хеш-кода, если возможно perfect hash function.

Код конструкции словаря не отображается в вашем примере, но если вы используете конструктор по умолчанию, тогда словарь будет использовать сопоставитель по умолчанию EqualityComparer<string>.Default.

Предоставление собственного сравнения со временем & Функция эффективного использования пространства может ускорить выполнение кода.

Если вы не знаете, как хорошая хэш-функция должна выглядеть в вашем случае, а затем с помощью интернированных строк также может дать вам некоторое повышение (см http://www.dotnetperls.com/string-intern (или MSDN: String.Intern Method))

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