Pull to refresh

Comments 15

Сам FieldCache использую в своем проекте (через NuGet). Не уверен, что кому-то нужен сам пакет, потому что гениального тут ничего нет, и, вероятно, проще написать свой велосипед.


Я использую эту штуку в своей библиотеке символьной алгебры, в которой такой паттерн чертовски полезен для математических выражений. Например, у математического выражения есть свойства InnerSimplified, Evaled, IsFinite и прочие, которые необходимо кешировать, так как количество обращений к ним непредсказуемо.


Примеры: InnerSimplified, Evaled.


Тут вызываются рекурсивные методы, которые в общем случае должны были бы обходить все дерево выражения. В данном случае, при первом обращении к свойству, вычисления будут происходить основываясь на свойствах детей. К примеру, если мы хоть раз обратились к свойству Evaled у выражения 2^5, то при обращении к этому же свойству у выражения 2^5 + 3 у нас не будет заново вычисляться 2^5. И это, по моему мнению, должно инкапсулироваться именно холдером, чтобы при обращении к свойству ни о чем думать не нужно было, и считать это обращение — бесплатным.

UFO just landed and posted this here

Это и есть ленивая инициализация. Но так как у нас неизменяемые объекты, то и сами закешированные значения никогда не станут неверными

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

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

Да, верно. А вот что значит "искать начало и конец инициализации" — не очень понятно. Если вы хотите что-то отдебажить, достаточно изолировать ваш объект от других, и при первом обращении попадете туда, куда нужно. Хотя можно и проще: поставить условные бряки и когда-нибудь ваш метод вызывется.

Если честно, мне не совсем понятно почему нельзя сделать похожую обертку над Lazy, вместо того чтобы изобретать свой велосипед, который, будем откровенными, получился практически на порядок медленнее Lazy и содержит потенциальные проблемы в реализации double-checked locking анти-паттерна. Ну и, в добавок, lock(this) я тоже не назвал бы удачным ходом.

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

я перефразирую, не делайте плз так в продакшн коде, это плохая идея, по этим граблям рано или поздно ходит каждый разработчик на С#
смотрите в сторону отдельных функций это даст вам больше степеней свободы:
как их компоновать и где и как долго хранить результаты
это другая ответственность


PS я просто оставлю это тут
https://github.com/Aaronontheweb/FastAtomicLazy/tree/master/FastAtomicLazy

Вы можете сказать, в чем грабли?


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


А ваших аргументов я пока не услышал.

вот пример, не увернен насчет рекордов
https://codereview.stackexchange.com/questions/129081/property-caching
но как вы думаете почему после изобретения всех подходов для CachedProperty
автор вопроса всеравно пришел к стандартному?


 Lazy<int> LazyMul;
 public override int Mul => LazyMul.Value;

LazyInitializer требует референса на тип (или на булеву), ничто из чего я могу себе позволить в рекорде

Я уже говорил, почему приватное поле с Lazy я не могу позволить себе. И я же в итоге делаю что-то похожее, просто лишенное недостатков классического подхода.


И на всякий случай скажу: меня верно подправили выше, это скорее ленивая инициализация, а не кеш, потому что в ленивой инициализации не надо ничего инвалидировать (в отличии от топика, что вы кинули).

скажите, а зачем вам lock (@this) если у вас тип неизменяемый?
Ну вызовет кто-то его два раза, в худшем случае где-то будет «нетот» трипл. Но у него будет тот же hash и то же value что и «правильного» трипла — не вижу в чем проблема (а зато выигрыш в скорости без лока и второй проверки можете сами прикинуть)

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


Другое дело, что вероятно есть более быстрые способы, но моя задача была показать дизайн, а не сделать самый быстрый lazy

Sign up to leave a comment.

Articles