-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use MemoryCache instead of WeakReference dictionary #101
Comments
Sounds like a good idea. System.Runtime.Caching can be used on netstandard2.0 so it would still work for the full framework. I don't see net45 listed, but perhaps that's because it is no longer supported. You'd probably want to use the singleton instance MemoryCache.Default. |
According to the docs .NET Framework 4+ is supported. Would you like to make a PR? |
I think the idea behind using |
The current implementation looks not good, every time on compiling expression it cleans the cache. Also the life of such cache is not big and will be flushed on every GC. Upd: this sample from https://github.com/ncalc/ncalc: This example uses Newtonsoft.Json. Serializing
Deserializing
|
Fair point, but if you had a reference to the LogicExpression woudln't you just use it rather than asking NCalc again? It's good to highlight that whatever settings chosen for CacheItemPolicy would be opinionated, and even with new arguments it still might not satisfy all use cases. Over here , I questioned the potential overhead of pruning the cache on every single compilation. If you have a use case where you're maintaining strong references for many expressions, or there is so much memory that GC doesn't happen very often, you could spend a lot of time iterating over the cache for every new compilation. What do you think about tracking the number of compilations and clean the cache on some predefined interval? It could also be done via a scheduled Timer.
|
We can also introduce a sort of background service to track and clean cache, but the MemoryCache still more customizable |
Yes, that would be the ideal way of caching and pretty much what I meant when I said full caching should probably live outside the library. The caching we have right now is just an optimization for heavy loads where an application keeps asking for the same expressions over and over again. I've used this in the past in a web application where we'd compute some user/session specific values with expressions and there are many independent requests in parallel. You get a nice speed up by not re-parsing the expressions all the time, and at the same time you can still rely on the GC to eventually recycle them and don't have to worry about an extra caching layer. I probably wouldn't want to take NCalc further than this heavy-load optimization in terms of caching and defer the rest to the user.
I do agree that pruning the cache on every new expression parsing step is probably excessive. Could we use |
Introducing the |
I'd agree that IDisposable seems like a breaking change in terms of expected contract as it implies Would something like this work?
The cache would then be defined as follows. I assume that once all strong references to LogicalExpression are lost, the CacheEntry can be collected, calling the finalizer and thus cleaning up the cache. I'm pretty sure the GC collects finalizers last, which may limit the aggression of LogicalExpression collection.
|
I don't think this gonna work - this would trigger when the We could just do this
We don't need the full |
I went down he rabbit hole and found this relevant thread. One other thing I found mentioned is that the finalizer approach could be problematic if the cache dictionary is collected at the same time as the Expression. Unfortunately, this is almost identical to what I recommended. |
Right now
WeakReference
is used for cache purpose, but it was not a good idea to use it as it's a short-lived and you can't control when it'll be flushed. I think it'll be better to replace it with MemoryCache@david-brink-talogy, what do you think about it?
The text was updated successfully, but these errors were encountered: