One of the performance enhancements I'd like to contribute relates to optimizing eviction handling filter eviction nodes.
Can you give me your thoughts on the proposed change below?
- In my scenario using JBossCache, I have certain subtrees in the cache that must be treated atomically from an eviction perspective. i.e. I can't allow just one branch of the subtree to be evicted. The whole subtree needs to be evicted at once, not just piece by piece.
- In JBoss 1.2.3 and prior, it was possible to support this scenario by implementing my own eviction policy (CascadingLRUPolicy) by subclassing LRUPolicy and overriding the evict() method.
- Since my "atomic subtrees" always started just off the cache root so I just ignored any evict() calls except where Fqn.size() == 1.
- I then made a further optimization by overriding the TreeCacheListener methods implemented on LRUPolicy to filter out any eviction events prior to them getting inserted into the bounded buffer. The rational was that since I wasn't interesed in evicting certain nodes, I could save a bunch of time by simply causing JBossCache to ignore those events in the first place.
- The result was a big jump in performance and scalability in my tests.
- While it is still possible to implement the evict() portion of my CascadingLRUPolicy, it looks like some refactoring and redesign in 1.2.4 of how eviction policies and the region manager interract makes it impossible to implement the filtering optimiziation.
- So here's what I've done to re-add the functionality based on the current JBoss 1.2.4 (head):
- added a new method called EvictionPolicy.canIgnoreEvent(Fqn)
- canIgnoreEvent is called by RegionManager.EvictionTreeCacheListener prior to adding the event to the region event buffer.
- if canIgnoreEvent returns true, the event is not added to the region event buffer
- if canIgnoreEvent returns false (default), the event is added to the region event buffer as normal
- added calls to EvictionPolicy.canIgnoreEvent in EvictionTreeCacheListener and AOPEvictionTreeCacheListener
- provide default implementation of canIgnoreEvent that always returns false
1. There is a major refactoring of eviction policy done by Daniel Huang. I will alert him of this post.
2. Is canIgoreEvent somewhat configurable? Or how do you determine which event to ignore?
3. We already have a Jira to do evict the whole sub-tree. Actually, implementation is not that diffcult, it will be just remove(subtree) except notification events wise.
Answers to your questions are below:
1. When is the refactoring of eviction planned for release? I realy would like to get this optimization in as soon as possible, especially considering 1.2.4 actually prevents me from making this optimization in a custom EvictionPolicy.
2. canIgnoreEvent is isn't configurable on an event by event basis. You either care about eviction events for a given node or you don't. I don't think it would make sense to care about a visit event but not an add event for eviction.
3. The Jira issue for sub-tree eviction originally came from my post about a year ago. Whole sub-tree eviction might make sense to have in the core so that it can work across all eviction policies, but my CascadingLRUPolicy does that just fine - the implementation was trivial.
Daniel has checked in the chantges to jbosscache head. I assume you will be interested to work on your optimization there as well? Like I said, it is almost done so all you need is to alert with him about the changes.
No problem so far with the other points.
Thanks - I'll work from jbosscachehead and post a new topic here about my changes for Daniel and others to review.
Sorry for getting to this late. I just got back from vacation.
Is canIgnoreEvent(Fqn) doing a match on Fqn to determine whether or not eviction events to that given node can be ignored? I am under the assumption that it is going to return false for everything unless the event is the top level node (e.g. /a will return false and /a/b/c will return true). Since you are using Fqn.size() == 1 then that is the case. Please take into account that we should be able to provide a configuration option specific to CascadingLRUPolicy that will define what should be considered the 'top level' node. You can do this by implementing a CascadingLRUConfiguration and writing the custom XML parsing for it encapsulated in that class. See the others for examples.
Otherwise the rest of it sounds fine. Thanks for the work! :)
Yes, canIgnoreEvent(Fqn) is (in my case) just checking the Fqn size, but of course in other situations someone might be doing it on a regexp pattern or what have you (although I suspect size will be the most common).
In my situation canIgnoreEvent returns true only if fqn.size()==1. That's because everything below that level must be evicted atomically with the parent.
Implementing a CascadingLRUConfiguration would be the way to do it if there was some need to configure this, but in my case that's not the situation.
Note that I hadn't been planning to check-in my CascadingLRUPolicy, but of course I could if required. I just figured we'd probably want to do this "right" in the future using a capability to do sub-tree eviction that worked across all policies... come to think of it, maybe I'll get cracking on that.
This change is done.