Каков наиболее эффективный способ хранения/извлечения элементов в asp.net httpContext.Cache
У меня есть сайт, на котором я кеширую много информации. Я вижу противоречивую информацию о хранении содержимого в кэше asp.net.
Например, скажем, у меня есть эта структура данных:
Dictionary<string, List<Car>> mydictionary;
Я мог бы сохранить все это с помощью строкового ключа как "MyDictionary", а затем развернуть его, как только вытащить объект.
HttpContext.Cache.Add("MyDictionary",
mydictionary,
null,
Cache.NoAbsoluteExpiration,
new TimeSpan(10, 0, 0),
CacheItemPriority.Normal,
null);
var myDict = HttpContext.Cache["MyDictionary"] as Dictionary<string, List<Car>>;
Другая вещь, которую я мог бы сделать, это разбить ее и сохранить каждый элемент в моем словаре отдельно в кеше (учитывая, что кеш - это словарь).
Dictionary<string, List<Car>> mydictionary;
foreach (var item in mydictionary.Keys)
{
HttpContext.Cache.Add(item, mydictionary[item], null, Cache.NoAbsoluteExpiration, new TimeSpan(10, 0, 0), CacheItemPriority.Normal, null);
}
var myitem = "test";
var myDict = HttpContext.Cache[myItem] as List<Car>;
Было бы очень сильно отличаться представление производительности (учитывая, что я предполагаю, что все равно в памяти?)
Ответы
Ответ 1
Добавление дополнительного ответа здесь, поскольку я чувствую, что существующее фиксирует "что", но недостаточно "почему".
Причина, по которой лучше хранить отдельные записи отдельно в кеше, имеет мало общего с перфомансом. Вместо этого это связано с тем, что система может выполнять правильное управление памятью.
В кеше ASP.NET существует много логики, чтобы выяснить, что делать, когда она сталкивается с давлением памяти. В конце концов, ему нужно выталкивать некоторые предметы, и это нужно сделать наименее разрушительным способом. Какие элементы, которые он выбрал для выключения, зависят от того, были ли они недавно получены. Существуют и другие факторы, например, какие флаги передаются во время кэширования. например вы можете сделать элемент несъемным, и его никогда не выбьют.
Но, возвращаясь к вопросу, если вы сохраняете весь словарь в виде одного элемента, вы оставляете только два варианта диспетчера памяти ASP.NET: держите все в живых или убивайте все это. т.е. вы полностью теряете выгоду от того, чтобы ваши "горячие" элементы оставались в кеше, в то время как ваши редко доступные объекты для хранения памяти выбиваются из игры. Другими словами, вы теряете любой уровень кеширования.
Конечно, вы могли бы реализовать свою собственную схему в своем словаре, чтобы удалить элементы, которые редко используются. Но в этот момент вы изобретаете колесо, и ваше новое колесо не будет работать, так как оно не будет координировать работу с остальной системой.
Ответ 2
Как вы говорите, есть два противоположных мнения по этому поводу.
На самом деле это сводится к тому, что записи кэша, вероятно, должны храниться на самом узком уровне по мере необходимости. Под этим я имею в виду, что если вы используете каждую запись в своем словаре каждый раз, когда она используется, сохраните ее на уровне словаря.
Если вы используете только один элемент из словаря, и вы не ходите по словарю, а затем храните его на отдельном уровне.
Итак, если вы обрабатываете всю коллекцию как единое целое, то кешируйте ее как единое целое. Если коллекция случайным образом доступна, и только определенные элементы необходимы за раз, а затем сохраните ее на уровне, на котором он является единственным элементом.
Ответ 3
Скорее всего, второй способ лучше.
Подумайте, стоит ли рассматривать многие объекты. Каждый раз, когда вам нужно получить 1 значение, вам нужно будет только его получить, вместо того, чтобы захватывать словарь энтира и, из этого, получить то, что вы хотите.
Это, не говоря о алгоритмах, используемых в кеше, для определения приоритетности наиболее используемых элементов (MRU, если я все еще помню).
Я просто рекомендую вам измерить прирост производительности с этим, прежде чем принимать его в качестве окончательной реализации.