From: Stephen Morris Date: Fri, 16 Mar 2012 15:35:34 +0000 (+0000) Subject: [1688] Add optimisation for RBNodeRRsets X-Git-Tag: trac2351_base~226^2~116^2~66^2~10^2~16 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a7f2ef92fd007ffc44e2e2572d0390efe8fcf901;p=thirdparty%2Fkea.git [1688] Add optimisation for RBNodeRRsets Reduce the cost of comparing RRsets when ignoring duplicate ones in the preparation of an output message. --- diff --git a/src/lib/datasrc/rbnode_rrset.h b/src/lib/datasrc/rbnode_rrset.h index 3e5d20a803..43814b481b 100644 --- a/src/lib/datasrc/rbnode_rrset.h +++ b/src/lib/datasrc/rbnode_rrset.h @@ -141,6 +141,25 @@ public: } } + virtual bool lthan(const AbstractRRset& other) const { + // Like "isSameKind", this method is an optimisation for the case where + // there will only ever be one object containing a particular RRset, + // and if the objects are different, the RRset they represent are + // different. + // + // lthan() is only used as an ordering for objects like std::set. + // Therefore the only criteria is that two objects are consistently + // ordered in the same way. The quickest way to do this is to use + // a comparison based on the address of the objects. + const RBNodeRRset* rb = dynamic_cast(&other); + if (rb != NULL) { + return (this < rb); + } else { + return (AbstractRRset::lthan(other)); + } + } + + virtual unsigned int toWire( isc::dns::AbstractMessageRenderer& renderer) const; diff --git a/src/lib/datasrc/tests/rbnode_rrset_unittest.cc b/src/lib/datasrc/tests/rbnode_rrset_unittest.cc index c653f44653..069307059b 100644 --- a/src/lib/datasrc/tests/rbnode_rrset_unittest.cc +++ b/src/lib/datasrc/tests/rbnode_rrset_unittest.cc @@ -12,6 +12,8 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. +#include +#include #include #include @@ -155,6 +157,84 @@ TEST_F(RBNodeRRsetTest, isSameKind) { EXPECT_FALSE(rrset_p.isSameKind(rrset_z)); } + +// Utility function to create an add an RRset to a vector of RRsets for the +// "less" test. It's only purpose is to allow the RRset creation to be +// written with arguments in an order that reflects the RRset ordering. +void +addRRset(std::vector& vec, const RRType& rrtype, + const RRClass& rrclass, const char* rrname) +{ + vec.push_back(ConstRRsetPtr(new RRset(Name(rrname), rrclass, rrtype, + RRTTL(3600)))); +} + +TEST_F(RBNodeRRsetTest, lthan) { + // Check values of type codes: this effectively documents the expected + // order of the rrsets created. + ASSERT_EQ(1, RRType::A().getCode()); + ASSERT_EQ(2, RRType::NS().getCode()); + + ASSERT_EQ(1, RRClass::IN().getCode()); + ASSERT_EQ(3, RRClass::CH().getCode()); + + // Create a vector of RRsets in ascending (conventional) sort order. + std::vector rrsets; + addRRset(rrsets, RRType::A(), RRClass::IN(), "alpha.com"); + addRRset(rrsets, RRType::A(), RRClass::IN(), "beta.com"); + addRRset(rrsets, RRType::A(), RRClass::CH(), "alpha.com"); + addRRset(rrsets, RRType::A(), RRClass::CH(), "beta.com"); + + // ... and create eight RBNodeRRsets for the underlying objects (two + // sets of four - the reason becomes apparent below). + std::vector rbrrsets; + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < rrsets.size(); ++j) { + rbrrsets.push_back(ConstRRsetPtr(new RBNodeRRset(rrsets[j]))); + } + } + + // Using the first four of the RBNodeRRsets, check that they order + // correctly when compared with the standard RRsets. + for (int i = 0; i < rrsets.size(); ++i) { + for (int j = 0; j < rrsets.size(); ++j) { + stringstream ss; + ss << "Comparing RbNodeRRset[" << i << "] against RRset[" + << j << "]"; + SCOPED_TRACE(ss.str()); + if (i < j) { + EXPECT_TRUE(rbrrsets[i]->lthan(*rrsets[j])); + } else { + EXPECT_FALSE(rbrrsets[i]->lthan(*rrsets[j])); + } + } + } + + // Put the raw pointers of the eight RBNodeRRsets into a vector and + // sort in ascending order. + std::vector rbptrs; + for (int i = 0; i < rbrrsets.size(); ++i) { + rbptrs.push_back(rbrrsets[i].get()); + } + sort(rbptrs.begin(), rbptrs.end()); + + // Now iterate through and check the relationships. Addresses with lower + // indexes should sort lower than addresses with higher indexes, regardless + // of what they point to. + for (int i = 0; i < rbptrs.size(); ++i) { + for (int j = 0; j < rbptrs.size(); ++j) { + stringstream ss; + ss << "Comparing address[" << i << "] against address[" << j << "]"; + SCOPED_TRACE(ss.str()); + if (i < j) { + EXPECT_TRUE(rbptrs[i]->lthan(*rbptrs[j])); + } else { + EXPECT_FALSE(rbptrs[i]->lthan(*rbptrs[j])); + } + } + } +} + // Note: although the next two tests are essentially the same and used common // test code, they use different test data: the MessageRenderer produces // compressed wire data whereas the OutputBuffer does not.