У меня есть метод, который принимает DateTime
и возвращает дату, обозначающую конец этой четверти. Из-за некоторой сложности, связанной с деловыми днями и праздничными календарями, я хочу кэшировать результат, чтобы ускорить последующие вызовы. Я использую SortedSet<DateTime>
поддерживать кэш данных, и я использую метод GetViewBetween
для того, чтобы сделать поиск в кэше следующим образом:Использование ImmutableSortedSet <T> для кеша потоковой безопасности
private static SortedSet<DateTime> quarterEndCache = new SortedSet<DateTime>();
public static DateTime GetNextQuarterEndDate(DateTime date)
{
var oneDayLater = date.AddDays(1.0);
var fiveMonthsLater = date.AddMonths(5);
var range = quarterEndCache.GetViewBetween(oneDayLater, fiveMonthsLater);
if (range.Count > 0)
{
return range.Min;
}
// Perform expensive calc here
}
Теперь я хочу, чтобы мой кэш поточно. Вместо того, чтобы использовать блокировку повсюду, которая повлечет за собой удар производительности при каждом поиске, я изучаю новую коллекцию ImmutableSortedSet<T>
, которая позволит мне полностью избежать блокировок. Проблема в том, что ImmutableSortedSet<T>
не имеет метода GetViewBetween
. Есть ли способ получить аналогичную функциональность от ImmutableSortedSet<T>
?
[EDIT]
Servy убедил меня только с помощью замка с нормальным SortedSet<T>
является самым простым решением. Я оставлю вопрос открытым, хотя только потому, что мне интересно узнать, может ли ImmutableSortedSet<T>
эффективно обрабатывать этот сценарий.
Самый простой вариант, вероятно, будет просто использовать блокировку чтения/записи вокруг набора. Создание неизменяемого набора не просто мгновенно устраняет все проблемы синхронизации, так как вы по-прежнему мутируете переменную, содержащую коллекцию. – Servy
@Servy Обмен ссылкой на переменные во вставке является атомарным. Худший вариант сценария заключается в том, что дорогостоящий калькулятор выполняется повторно без необходимости, если поиск происходит до обновления кеша, но преимущество в том, что нам не нужно получать блокировку для каждого поиска; в случае одного потока нет накладных расходов на блокировку, а в случае с несколькими потоками нет конфликта блокировок. – jjoelson
Но вам также необходимо ввести барьеры памяти для наблюдаемых изменений. И стоимость перерасчета дорогостоящих вычислений будет полностью затмевать затраты на вывоз неоспоримой блокировки. Незаконченные блокировки * очень * дешевы для приобретения. – Servy