BIND 10 #192: Data source hotspot cache

BIND 10 Development do-not-reply at isc.org
Wed Jun 23 07:09:35 UTC 2010


#192: Data source hotspot cache
-------------------------+--------------------------------------------------
 Reporter:  each         |        Owner:  jinmei                                        
     Type:  enhancement  |       Status:  reviewing                                     
 Priority:  major        |    Milestone:  05. 3rd Incremental Release: Serious Secondary
Component:  b10-auth     |   Resolution:                                                
 Keywords:               |    Sensitive:  0                                             
-------------------------+--------------------------------------------------
Changes (by each):

  * owner:  each => jinmei


Comment:

 > !CacheEntry class
 > !CacheNode class

 By changing the signature of HotCache::retrieve(), I was able to
 refactor both of these into a completely hidden objects in cache.cc,
 I hope this addresses most of your concerns with the code.  I'll also
 update them tomorrow with the suggestions you made for their
 documentation, but I haven't done that yet.

 > QTuple class

 I've removed this class entirely, in favor of isc::dns::Question (which
 has
 had an an less-than operator added to it for use by std::map).

 > We tend to abbreviate things, but isn't it better to name it more
 clearly, e.g., !HotSpotCache

 I personally prefer !HotCache, but it's not particularly important to me.
 I'll change it if you think it's important.

 > Class description: like Cachenode, I'd add more design decisions, non
 trivial points, etc.

 Okay, I've done some of that...

 > As for design decision, I guess we need to consider multi-thread
 considerations.

 Good point.  Documented.

 > Design: I don't think making this as a static is a good idea.

 We discussed this further, and I'm convinced.  HotCache is now
 instantiated
 a member of AuthSrvImpl.

 > Design: now the controversial point:-) I strongly suggest >pimpl be used
 for this class.

 Done.

 > I believe the HotCache? </wiki/HotCache> class is intended to be non-
 copyable. Please explicitly make it so.

 Done.

 > naming: if we follow our method name convention, cache() is better named
 setCacheEntry()

 I had been thinking of the word cache() as a verb, not a noun, but since
 there's now a cache() function in the Query objct now that returns a
 reference to the HotCache, I decided you're right about this.  I chose the
 names addPositive() and addNegative().

 > description about cache(): it should describe what happens if there's
 already an entry that matches the key. Also also be tested.

 Done.

 > HotCache::~HotCache(): I don't understand what the for loop does. Does
 this do something correct? Also recall my other comment about why using
 in-house list. If we use std::list, we don't even have to bother to clean
 up these things.

 I'm pretty sure this is correct, now that I've fixed the for loop.

 > HotCache::retrieve(): map::operator[] creates a new entry if it doesn't
 have one for the key. It's probably not necessarily incorrect, but I
 suspect it's error-prone behavior. For example, consider the case where
 the caller continuously calls retrieve() for different non-existent keys.
 I suggest you use map::find() instead.

 Done.

 > HotCache::insert(): why do we need to have a while loop?

 Changed to an if (and an assert()).

 > HotCache::ncache(): the condition of ANY()s isn't documented (and not
 intuitive).

 Documented.

 > please don't hardcode flags (e.g. for the second arg of
 HotCache::cache()), even though it's opaque for the HotCache module

 Not yet done, but I will get to it tomorrow.

 > I see the effect of checking the cache before trying to identify the
 best data source. But that doesn't mean you have to alter the definition
 and interfaces of an existing class (NameMatch), affecting many other
 parts of code that have nothing to do with hot spot caching. That was my
 point.

 If you prefer, you could think of it as eliminating a class that's no
 longer needed (!NameMatch) and replacing it with one that serves our
 needs better (!ZoneInfo).

 The !NameMatch class is *not* a pristine general-purpose class; its sole
 function, prior to this change, was the one it's still being used for now:
 to iterate through through a list of data sources looking for the one that
 is authoritative for a given name.  There is no other use to which it can
 be put.  It already had several quirks, such as the special-case code for
 rrtype==DS.

 I haven't really changed it, I've just given it a slightly broader remit,
 in order to eliminate unnecessary database searches.  I don't think
 there's
 any simpler way to accomplish this that still makes sense.

 > For example, you changed !NameMatch, the signature of
 DataSrc::findClosestEnclosure() has also changed, affecting many other
 data source implementations and unit tests. One specific case is this:
 >
 > This is totally irrelevant to hot spot caching, and I saw many such
 changes. They are distracting.

 I don't agree that it's irrelevant--though perhaps it's a little
 tangential.  In the interests of making it easier to review, I can change
 the signature of findClosestEnclosure() back to what it was--but I would
 still want to make this change as soon as possible afterward, because IMHO
 it's a bug waiting to happen.  You specify a class when you create the
 !ZoneInfo object; if you then call findClosestEnclosure() with a
 *different* class, it would cause a confusing failure.  It makes a lot
 more
 sense to preserve the information you used when you created the !ZoneInfo
 object.

 However, if you think it's urgent that split this into multiple separate
 fixes, I can do that.

 For the present, however, what I've done is to fully commit to the change
 I
 had made before: I've changed the NameMatch class to be called ZoneInfo,
 which is clearer and more descriptive.  As I say, however, if you think
 it's necessary to split this into multiple changes, I will attempt it
 tomorrow.

 > So, while I don't insist std::list is definitely better in this case, I
 would suggest you at least try a version with std::list, not just making a
 decision based on seeming observation. If, after playing with both ways,
 you are still sure the advantage of in-house implementation outweighs its
 negative consequences, it's your call.

 I have now tried it with std::list, but I think it will damage performance
 (unless I've missed some key features of std::list, which is certainly
 possible).

 As near as I can tell, to use a std::list, I would have to promote entries
 by to the head of the list by using list::remove() followed by
 list::push_front().  But list::remove() works by iterating over the list
 searching for entries with the matching value to remove.

 As I've currently written it, you get access to the !CacheNode in O(log n)
 time via the std::map, and then you can promote it to the head of the list
 in constant time.  With std::list, the promotion would be O(n).

 > One thing I cannot understand is the loop condition:
 >
 >     for (node = lru_head_; node = node->next; node != CacheNodePtr()) {

 Oops, yes, I had reversed the second and third statements.

-- 
Ticket URL: <https://bind10.isc.org/ticket/192#comment:22>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list