ZiggyCreatures / FusionCache

FusionCache is an easy to use, fast and robust hybrid cache with advanced resiliency features.
MIT License
1.87k stars 96 forks source link

[BUG] unexpected high memory consumption with auto-clone #315

Open JoHohner opened 1 month ago

JoHohner commented 1 month ago

Currently we only use the in-memory cache with the auto-clone feature and message pack. We observed a high memory consumption when using the cache so we played a bit with it. When storing serialized data in the cache instead of relying on auto-clone, the memory numbers were much lower. So we looked into a profiler and the code and saw, that the cache still holds a reference to the original value, even after serializing it.

Is there a reason to not free the value?

My understanding is, that FusionCacheMemoryEntry.GetSerializedValue(IFusionCacheSerializer serializer) could / should set Value to null after serializing it, so the original object can be garbage collected.

jodydonetti commented 1 month ago

Hi @JoHohner

Currently we only use the in-memory cache with the auto-clone feature and message pack. We observed a high memory consumption when using the cache so we played a bit with it. When storing serialized data in the cache instead of relying on auto-clone, the memory numbers were much lower. So we looked into a profiler and the code and saw, that the cache still holds a reference to the original value, even after serializing it.

Correct, as of today that is the behaviour.

Is there a reason to not free the value?

The reason is that auto-clone is an option that can be specified per-call: this means that when you ask for the data you can choose if you want it cloned or not, on a call-by-call basis. Because of this I store the object as normal, plus the byte[] only if needed (lazily, the first time is needed), but keep the object too for other callers.

My understanding is, that FusionCacheMemoryEntry.GetSerializedValue(IFusionCacheSerializer serializer) could / should set Value to null after serializing it, so the original object can be garbage collected.

This is an interesting approach, which I'll look into. I need to consider consequences of that and some edge cases, but I'll give it a shot. Maybe this behaviour can be a global option (meaning, per-cache instead of per-call/per-entry).

Now I'm onto the tagging feature which is a big hairy monster, but will ook into this as soon as possible.

Thanks for pointing it out!

JoHohner commented 1 month ago

Is there a reason to not free the value?

The reason is that auto-clone is an option that can be specified per-call: this means that when you ask for the data you can choose if you want it cloned or not, on a call-by-call basis. Because of this I store the object as normal, plus the byte[] only if needed (lazily, the first time is needed), but keep the object too for other callers.

Ah, okay. I didn't know that. So it is intentional atm.

Now I'm onto the tagging feature which is a big hairy monster, but will ook into this as soon as possible.

Take your time, we have a workaround. Tagging is also something we appreciate.