|
@@ -0,0 +1,246 @@
|
|
|
+// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
|
|
|
+//
|
|
|
+// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
+// purpose with or without fee is hereby granted, provided that the above
|
|
|
+// copyright notice and this permission notice appear in all copies.
|
|
|
+//
|
|
|
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
|
|
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
|
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
|
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
|
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
+// PERFORMANCE OF THIS SOFTWARE.
|
|
|
+
|
|
|
+#include <bench/benchmark.h>
|
|
|
+
|
|
|
+#include <util/buffer.h>
|
|
|
+#include <util/memory_segment_local.h>
|
|
|
+
|
|
|
+#include <dns/name.h>
|
|
|
+#include <dns/messagerenderer.h>
|
|
|
+#include <dns/rrset.h>
|
|
|
+#include <dns/rrclass.h>
|
|
|
+#include <dns/masterload.h>
|
|
|
+
|
|
|
+#include <datasrc/memory/rdata_serialization.h>
|
|
|
+#include <datasrc/memory/rdataset.h>
|
|
|
+#include <datasrc/memory/treenode_rrset.h>
|
|
|
+#include <datasrc/memory/zone_data.h>
|
|
|
+
|
|
|
+#include <boost/bind.hpp>
|
|
|
+
|
|
|
+#include <cassert>
|
|
|
+#include <vector>
|
|
|
+#include <sstream>
|
|
|
+
|
|
|
+#include <unistd.h>
|
|
|
+
|
|
|
+using std::vector;
|
|
|
+using namespace isc::bench;
|
|
|
+using namespace isc::datasrc::memory;
|
|
|
+using namespace isc::dns;
|
|
|
+
|
|
|
+namespace {
|
|
|
+// A simple benchmark just repeating rendering a given set of RRsets.
|
|
|
+class RRsetRenderBenchMark {
|
|
|
+public:
|
|
|
+ RRsetRenderBenchMark(const vector<ConstRRsetPtr>& rrsets,
|
|
|
+ MessageRenderer& renderer) :
|
|
|
+ rrsets_(rrsets), renderer_(renderer)
|
|
|
+ {}
|
|
|
+ unsigned int run() {
|
|
|
+ renderer_.clear();
|
|
|
+ vector<ConstRRsetPtr>::const_iterator it;
|
|
|
+ const vector<ConstRRsetPtr>::const_iterator it_end = rrsets_.end();
|
|
|
+ for (it = rrsets_.begin(); it != it_end; ++it) {
|
|
|
+ (*it)->toWire(renderer_);
|
|
|
+ }
|
|
|
+ return (1);
|
|
|
+ }
|
|
|
+private:
|
|
|
+ const vector<ConstRRsetPtr>& rrsets_;
|
|
|
+ MessageRenderer& renderer_;
|
|
|
+};
|
|
|
+
|
|
|
+// Builtin benchmark data. This is a list of RDATA (of RRs) in a response
|
|
|
+// from a root server for the query for "www.example.com" (as of this
|
|
|
+// implementation). We use a real world example to make the case practical.
|
|
|
+const char* const delegation_rrsets_txt =
|
|
|
+ // AUTHORITY SECTION (NS)
|
|
|
+ "com. 172800 IN NS a.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS b.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS c.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS d.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS e.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS f.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS g.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS h.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS i.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS j.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS k.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS l.gtld-servers.net.\n"
|
|
|
+ "com. 172800 IN NS m.gtld-servers.net.\n"
|
|
|
+ // AUTHORITY SECTION (DS)
|
|
|
+ "com. 86400 IN DS 30909 8 2 "
|
|
|
+ "E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CFC41A5766\n"
|
|
|
+ // AUTHORITY SECTION (RRSIG for DS)
|
|
|
+ "com. 86400 IN RRSIG DS 8 1 86400 20120822000000 20120814230000 50398 . "
|
|
|
+ "lcIpLRq4s91Fh1FihDXiDvVMMRqgy2jjlpiP4Y6sSjIrLue6Boi7xraj"
|
|
|
+ "Ouka34ubpl4KuIcopWe99LI/7Npvq0MYr9DaqfnX9dTW6Vc2C7/hKSsz"
|
|
|
+ "POYjraZZA3SCApgfNVzq+AscYlShi56f1vm7DQWw1eh1wHLdatidrQwNyDo=\n"
|
|
|
+ // ADDITIONAL SECTION
|
|
|
+ "a.gtld-servers.net. 172800 IN A 192.5.6.30\n"
|
|
|
+ "b.gtld-servers.net. 172800 IN A 192.33.14.30\n"
|
|
|
+ "c.gtld-servers.net. 172800 IN A 192.26.92.30\n"
|
|
|
+ "d.gtld-servers.net. 172800 IN A 192.31.80.30\n"
|
|
|
+ "e.gtld-servers.net. 172800 IN A 192.12.94.30\n"
|
|
|
+ "f.gtld-servers.net. 172800 IN A 192.35.51.30\n"
|
|
|
+ "g.gtld-servers.net. 172800 IN A 192.42.93.30\n"
|
|
|
+ "h.gtld-servers.net. 172800 IN A 192.54.112.30\n"
|
|
|
+ "i.gtld-servers.net. 172800 IN A 192.43.172.30\n"
|
|
|
+ "j.gtld-servers.net. 172800 IN A 192.48.79.30\n"
|
|
|
+ "k.gtld-servers.net. 172800 IN A 192.52.178.30\n"
|
|
|
+ "l.gtld-servers.net. 172800 IN A 192.41.162.30\n"
|
|
|
+ "m.gtld-servers.net. 172800 IN A 192.55.83.30\n"
|
|
|
+ "a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30\n"
|
|
|
+ "b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30";
|
|
|
+
|
|
|
+// Likewise, it's a response from a root server for www.example.notexistent.
|
|
|
+// An example that involves a few more RRSIGs.
|
|
|
+const char* const nxdomain_rrsets_txt =
|
|
|
+ // AUTHORITY SECTION (NS)
|
|
|
+ ". 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2012082901 1800 900 604800 86400\n"
|
|
|
+ ". 86400 IN RRSIG SOA 8 0 86400 20120905000000 20120828230000 50398 . Wj6NgkA2TyJug9XfWYG/Cjh4d1JI99/Dv9S1TClbrhLdeMI4s9BEcBSA xdlPJN6L4uaupcYeEyRWGx3p0iq7VWFyjL4xy/+jXpUoHCgj0NlWa6eu C2litcnfcumTI97XJ5iod3ET+6vWnhwZQHDnz1fj4FuS8PPEJJ+Oy3M5 mcM=\n"
|
|
|
+ ". 86400 IN NSEC ac. NS SOA RRSIG NSEC DNSKEY\n"
|
|
|
+ ". 86400 IN RRSIG NSEC 8 0 86400 20120905000000 20120828230000 50398 . f8FEG1HzQtn/shZCdDgkB7TIpHAmH2hGlp5RubczukzD8XI3EGMVNoaf 2cUNPLpyhoBQkO1Rz+hANzI6Jkqq8PzhiQnLcW+y2Wl/BU2SaBQ2Otb2 5+VOOXux1veKaCZsRRU1VJnTUYguDayAgcS7BtB/rc7ez4nokkK98MA9 zcw=\n"
|
|
|
+ "no. 86400 IN NSEC np. NS RRSIG NSEC\n"
|
|
|
+ "no. 86400 IN RRSIG NSEC 8 1 86400 20120905000000 20120828230000 50398 . Z/E4hb6MMSpueGGjGoCWwnN2uKsQf88HPS1gbwVHBEhR+5eSn0BGqExs fQsjYL47SF/6pwMXjzmXCt8NPXXf9ImY/93GUuFL6j5OuL2MDIxt24MS u6hfxxiYTn+zF0dM8cn+UK5n1VEBB5JVJXf7FOr3OmaRLMD33Gl6yZJ/ l1E=";
|
|
|
+
|
|
|
+void
|
|
|
+usage() {
|
|
|
+ std::cerr << "Usage: rrset_render_bench [-n iterations]" << std::endl;
|
|
|
+ exit (1);
|
|
|
+}
|
|
|
+
|
|
|
+// Helper callback for masterLoad() used in main() to build test data.
|
|
|
+void
|
|
|
+setRRset(vector<ConstRRsetPtr>* rrsets, ConstRRsetPtr rrset) {
|
|
|
+ rrsets->push_back(rrset);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+buildZone(isc::util::MemorySegmentLocal& mem_sgmt,
|
|
|
+ ZoneData* zone_data, const vector<ConstRRsetPtr>& rrsets,
|
|
|
+ vector<ConstRRsetPtr>& rrsets_build)
|
|
|
+{
|
|
|
+ RdataEncoder encoder;
|
|
|
+
|
|
|
+ for (vector<ConstRRsetPtr>::const_iterator it = rrsets.begin();
|
|
|
+ it != rrsets.end();
|
|
|
+ ++it)
|
|
|
+ {
|
|
|
+ ConstRRsetPtr rrset = *it;
|
|
|
+ ZoneNode* node;
|
|
|
+ zone_data->insertName(mem_sgmt, rrset->getName(), &node);
|
|
|
+
|
|
|
+ // For simplicity, we assume that if the current RRset has a next
|
|
|
+ // one that is of type RRSIG, that RRSIG should be associated with
|
|
|
+ // the current RRset (which should be the case for our test data).
|
|
|
+ ConstRRsetPtr sig_rrset;
|
|
|
+ if ((it + 1) != rrsets.end() &&
|
|
|
+ (*(it + 1))->getType() == RRType::RRSIG()) {
|
|
|
+ sig_rrset = *(++it);
|
|
|
+ }
|
|
|
+ RdataSet* rdataset =
|
|
|
+ RdataSet::create(mem_sgmt, encoder, rrset, sig_rrset);
|
|
|
+ rdataset->next = node->getData();
|
|
|
+ node->setData(rdataset);
|
|
|
+
|
|
|
+ rrsets_build.push_back(
|
|
|
+ ConstRRsetPtr(new TreeNodeRRset(rrset->getClass(), node, rdataset,
|
|
|
+ true)));
|
|
|
+ }
|
|
|
+}
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+main(int argc, char* argv[]) {
|
|
|
+ int ch;
|
|
|
+ int iteration = 100000;
|
|
|
+ while ((ch = getopt(argc, argv, "n:")) != -1) {
|
|
|
+ switch (ch) {
|
|
|
+ case 'n':
|
|
|
+ iteration = atoi(optarg);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ usage();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ argc -= optind;
|
|
|
+ argv += optind;
|
|
|
+ if (argc != 0) {
|
|
|
+ usage();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Build test data. rrsets will consist of a list of RRsets corresponding
|
|
|
+ // to the text defined above.
|
|
|
+ vector<ConstRRsetPtr> delegation_rrsets;
|
|
|
+ std::stringstream rrsets_stream(delegation_rrsets_txt);
|
|
|
+ masterLoad(rrsets_stream, Name::ROOT_NAME(), RRClass::IN(),
|
|
|
+ boost::bind(setRRset, &delegation_rrsets, _1));
|
|
|
+
|
|
|
+ vector<ConstRRsetPtr> nxdomain_rrsets;
|
|
|
+ std::stringstream rrsets_stream2(nxdomain_rrsets_txt);
|
|
|
+ masterLoad(rrsets_stream2, Name::ROOT_NAME(), RRClass::IN(),
|
|
|
+ boost::bind(setRRset, &nxdomain_rrsets, _1));
|
|
|
+
|
|
|
+ // Build in-memory zone using RRsets constructed above, storing
|
|
|
+ // the same set of RRsets as TreeNodeRRsets in separate vectors.
|
|
|
+ // This code below is not 100% exception safe (for simplicity), but at
|
|
|
+ // least it shouldn't leak memory in normal cases.
|
|
|
+ isc::util::MemorySegmentLocal mem_sgmt;
|
|
|
+ ZoneData* zone_data = ZoneData::create(mem_sgmt, Name::ROOT_NAME());
|
|
|
+ vector<ConstRRsetPtr> delegation_treenode_rrsets;
|
|
|
+ buildZone(mem_sgmt, zone_data, delegation_rrsets,
|
|
|
+ delegation_treenode_rrsets);
|
|
|
+ vector<ConstRRsetPtr> nxdomain_treenode_rrsets;
|
|
|
+ buildZone(mem_sgmt, zone_data, nxdomain_rrsets,
|
|
|
+ nxdomain_treenode_rrsets);
|
|
|
+
|
|
|
+ // The benchmark test uses a message renderer. Create it now and keep
|
|
|
+ // using it throughout the test.
|
|
|
+ isc::util::OutputBuffer buffer(4096); // 4096 should be sufficiently large
|
|
|
+ MessageRenderer renderer;
|
|
|
+ renderer.setBuffer(&buffer);
|
|
|
+
|
|
|
+ std::cout << "Benchmark for rendering basic RRsets (delegation)"
|
|
|
+ << std::endl;
|
|
|
+ BenchMark<RRsetRenderBenchMark>(iteration,
|
|
|
+ RRsetRenderBenchMark(delegation_rrsets,
|
|
|
+ renderer));
|
|
|
+
|
|
|
+ std::cout << "Benchmark for rendering tree node RRsets (delegation)"
|
|
|
+ << std::endl;
|
|
|
+ BenchMark<RRsetRenderBenchMark>(iteration,
|
|
|
+ RRsetRenderBenchMark(
|
|
|
+ delegation_treenode_rrsets, renderer));
|
|
|
+
|
|
|
+ std::cout << "Benchmark for rendering basic RRsets (nxdomain)"
|
|
|
+ << std::endl;
|
|
|
+ BenchMark<RRsetRenderBenchMark>(iteration,
|
|
|
+ RRsetRenderBenchMark(nxdomain_rrsets,
|
|
|
+ renderer));
|
|
|
+
|
|
|
+ std::cout << "Benchmark for rendering tree node RRsets (nxdomain)"
|
|
|
+ << std::endl;
|
|
|
+ BenchMark<RRsetRenderBenchMark>(iteration,
|
|
|
+ RRsetRenderBenchMark(
|
|
|
+ nxdomain_treenode_rrsets, renderer));
|
|
|
+
|
|
|
+ // Cleanup, and memory leak check
|
|
|
+ ZoneData::destroy(mem_sgmt, zone_data, RRClass::IN());
|
|
|
+ assert(mem_sgmt.allMemoryDeallocated());
|
|
|
+
|
|
|
+ return (0);
|
|
|
+}
|