Using MemoryCache to cache a collection of published content
Hi all,
We have a bit of a problem with a project we've been working on.
Basically, we had some expensive (in terms of time) node queries/transformations. These node queries end up being delivered by WebAPI (as JSON objects), or used within a view/partial view.
To optimise performance of the site, we've been caching the result of these node queries (an IEnumerable list of published content) using the MemoryCache class.
Performance is excellent - but we discovered an issue where by the web application started leaking memory - caused (we believe) by the caching of what is basically a live object with dependencies and links - which it seems cannot be properly disposed/cleaned up later when the cache object expires (at least, this is what our testing suggests).
So we need to refactor a small part of our solution (thankfully not a lot of code) to avoid this.
My first thought was that we could clone or serialise the object before storing in the MemoryCache - but it seems you can't do that with the Umbraco published content models.
The other alternative I thought of is to create a much simpler class (or Dictionary) containing only the properties of the class we need to consume later (as string, int etc.). Although this isn't ideal, because we'd like the potential to be able to access any property of the node later.
Just wondered if anyone else had come across this problem before (needing store the results of a node query in MemoryCache) - and if so, how you solved it without creating memory leaks :-)
We've possibly found a solution to this issue - or at least, it works on development (testing on production shortly).
Posting here in case anyone comes across the same issue.
When a MemoryCache cached item is expired, you can specify a callback function as part of the cache item policy. This exposes the cached item, which you then get the opportunity to call DisposeIfDisposable() on.
Making sure we do this each time an item in the cache expires, seems to have solved the problem.
To be honest, I'm not sure why it doesn't happen automatically - you'd imagine it should? But if it works on production, I'll be happy.
Using MemoryCache to cache a collection of published content
Hi all,
We have a bit of a problem with a project we've been working on.
Basically, we had some expensive (in terms of time) node queries/transformations. These node queries end up being delivered by WebAPI (as JSON objects), or used within a view/partial view.
To optimise performance of the site, we've been caching the result of these node queries (an IEnumerable list of published content) using the MemoryCache class.
Performance is excellent - but we discovered an issue where by the web application started leaking memory - caused (we believe) by the caching of what is basically a live object with dependencies and links - which it seems cannot be properly disposed/cleaned up later when the cache object expires (at least, this is what our testing suggests).
So we need to refactor a small part of our solution (thankfully not a lot of code) to avoid this.
My first thought was that we could clone or serialise the object before storing in the MemoryCache - but it seems you can't do that with the Umbraco published content models.
The other alternative I thought of is to create a much simpler class (or Dictionary) containing only the properties of the class we need to consume later (as string, int etc.). Although this isn't ideal, because we'd like the potential to be able to access any property of the node later.
Just wondered if anyone else had come across this problem before (needing store the results of a node query in MemoryCache) - and if so, how you solved it without creating memory leaks :-)
Thanks,
Steve.
We've possibly found a solution to this issue - or at least, it works on development (testing on production shortly).
Posting here in case anyone comes across the same issue.
When a MemoryCache cached item is expired, you can specify a callback function as part of the cache item policy. This exposes the cached item, which you then get the opportunity to call DisposeIfDisposable() on.
Making sure we do this each time an item in the cache expires, seems to have solved the problem.
To be honest, I'm not sure why it doesn't happen automatically - you'd imagine it should? But if it works on production, I'll be happy.
is working on a reply...