Browse Source

added a simple benchmark test for the RdataFields class compared to Rdata.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac404@3447 e5f2f494-b856-4b98-b285-d166d9295462
JINMEI Tatuya 14 years ago
parent
commit
22e21e7219

+ 1 - 0
configure.ac

@@ -513,6 +513,7 @@ AC_CONFIG_FILES([Makefile
                  src/lib/dns/tests/testdata/Makefile
                  src/lib/dns/python/Makefile
                  src/lib/dns/python/tests/Makefile
+                 src/lib/dns/benchmarks/Makefile
                  src/lib/exceptions/Makefile
                  src/lib/exceptions/tests/Makefile
                  src/lib/datasrc/Makefile

+ 1 - 1
src/lib/dns/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = . tests python
+SUBDIRS = . tests python benchmarks
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)

+ 17 - 0
src/lib/dns/benchmarks/Makefile.am

@@ -0,0 +1,17 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+noinst_PROGRAMS = rdatarender_bench
+rdatarender_bench_SOURCES = rdatarender_bench.cc
+
+rdatarender_bench_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
+rdatarender_bench_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+rdatarender_bench_LDADD += $(SQLITE_LIBS)

+ 10 - 0
src/lib/dns/benchmarks/README

@@ -0,0 +1,10 @@
+- rdatarender_bench
+
+  This is a benchmark for RDATA rendering performance comparing the basic
+  Rdata objects and RdataField objects.  It takes a command line argument
+  that specifies an input data file.  Each line of the data file should
+  specify a single RDATA with its RR class and type, e.g.
+  IN A 192.0.2.1
+  IN NS ns.example.com.
+  Lines beginning with '#' and empty lines will be ignored.  Sample input
+  files can be found in benchmarkdata/rdatarender_*.

+ 32 - 0
src/lib/dns/benchmarks/benchmarkdata/rdatarender_data_com

@@ -0,0 +1,32 @@
+# This is sample input data for rdatarender_bench.
+# These are RDATA in the authority and additional sections in a response from
+# a root server for a query domain under COM.
+
+IN	NS	g.gtld-servers.net.
+IN	NS	a.gtld-servers.net.
+IN	NS	k.gtld-servers.net.
+IN	NS	c.gtld-servers.net.
+IN	NS	d.gtld-servers.net.
+IN	NS	m.gtld-servers.net.
+IN	NS	h.gtld-servers.net.
+IN	NS	b.gtld-servers.net.
+IN	NS	j.gtld-servers.net.
+IN	NS	l.gtld-servers.net.
+IN	NS	e.gtld-servers.net.
+IN	NS	f.gtld-servers.net.
+IN	NS	i.gtld-servers.net.
+IN	A	192.5.6.30
+IN	A	192.33.14.30
+IN	A	192.26.92.30
+IN	A	192.31.80.30
+IN	A	192.12.94.30
+IN	A	192.35.51.30
+IN	A	192.42.93.30
+IN	A	192.54.112.30
+IN	A	192.43.172.30
+IN	A	192.48.79.30
+IN	A	192.52.178.30
+IN	A	192.41.162.30
+IN	A	192.55.83.30
+IN	AAAA	2001:503:a83e::2:30
+IN	AAAA	2001:503:231d::2:30

+ 10 - 0
src/lib/dns/benchmarks/benchmarkdata/rdatarender_data_nxdomain

@@ -0,0 +1,10 @@
+# This is sample input data for rdatarender_bench.
+# These are RDATA in the authority section in a response from
+# a root server for a non existent query domain (with DNSSEC).
+
+IN	SOA	a.root-servers.net. nstld.verisign-grs.com. 2010110301 1800 900 604800 86400
+IN	RRSIG	SOA 8 0 86400 20101110000000 20101102230000 40288 . WtvYyX2nIsaqjWqkIG1WHFE5PnJ6eno0KqF6azU/MFJ/t1JpKWQ1P4rA 61rnoq0p252fg7wT4XzEz9UDxmpB5pvF2VApe2w9LvSWxsWIIOg8ue5u e9NAAYdzjd0rsYObQQ6msf7WchyAUbnmrqKvf8/CK6+s1xFihXp5DpYL 6K0=
+IN	NSEC	ac. NS SOA RRSIG NSEC DNSKEY
+IN	RRSIG	NSEC 8 0 86400 20101110000000 20101102230000 40288 . rWfgg4YUDFAjhiUOT+niJy/qbaIbydqoXg5oB/5j//ZjNFy4hqU8DvdM xJr9UybQpEvu7pvmKQ0jRYO98Fw/UTlY5KiKbhVBJ1t8AE93cbU+s5gX d3Q6+wRcFX5MjZyIe+f30llKrYOZHjRyEFALCkLt4XEmr0xsua+ztAFY 65k=
+IN	NSEC	np. NS RRSIG NSEC
+IN	RRSIG	NSEC 8 1 86400 20101110000000 20101102230000 40288 . G32LGynsGA2fyDnesyeCtBCoM3ERMgGS4touDUuoBYW1NrZub76kz5fc z93p8VZfoYWAW7LuC8vJ1jl2sUgBNns4zN4RsfFeopcYjjFnGbGuoZnO NmTU+NKO53Ub7uIcCSeqV+COAaL8XqDfyk1FmVdQvtrBaOW/PWpRahVq 7E8=

+ 22 - 0
src/lib/dns/benchmarks/benchmarkdata/rdatarender_data_org

@@ -0,0 +1,22 @@
+# This is sample input data for rdatarender_bench.
+# These are RDATA in the authority and additional sections in a response from
+# a root server for a query domain under ORG.
+
+IN	NS	b0.org.afilias-nst.org.
+IN	NS	a2.org.afilias-nst.info.
+IN	NS	a0.org.afilias-nst.info.
+IN	NS	c0.org.afilias-nst.info.
+IN	NS	d0.org.afilias-nst.org.
+IN	NS	b2.org.afilias-nst.org.
+IN	A	199.19.56.1
+IN	A	199.249.112.1
+IN	A	199.19.54.1
+IN	A	199.249.120.1
+IN	A	199.19.53.1
+IN	A	199.19.57.1
+IN	AAAA	2001:500:e::1
+IN	AAAA	2001:500:40::1
+IN	AAAA	2001:500:c::1
+IN	AAAA	2001:500:48::1
+IN	AAAA	2001:500:b::1
+IN	AAAA	2001:500:f::1

+ 183 - 0
src/lib/dns/benchmarks/rdatarender_bench.cc

@@ -0,0 +1,183 @@
+// Copyright (C) 2010  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 <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <boost/shared_ptr.hpp>
+
+#include <bench/benchmark.h>
+
+#include <dns/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdatafields.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+using namespace std;
+using namespace isc::bench;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+
+namespace {
+// This templated benchmark class is constructed with a vector of Rdata-like
+// (pointer) objects which should have a "toWire()" method.  In its run(),
+// it calls toWire() for each element of the vector.
+template <typename T>
+class RdataRenderBenchMark {
+public:
+    RdataRenderBenchMark(const vector<T>& dataset) :
+        dataset_(dataset), buffer_(4096), renderer_(buffer_)
+    {}
+    unsigned int run() {
+        typename vector<T>::const_iterator data;
+        typename vector<T>::const_iterator data_end = dataset_.end();
+        for (data = dataset_.begin(); data != data_end; ++data) {
+            renderer_.clear();
+            (*data)->toWire(renderer_);
+        }
+        return (dataset_.size());
+    }
+private:
+    const vector<T>& dataset_;
+    OutputBuffer buffer_;
+    MessageRenderer renderer_;
+};
+
+// This supplemental class emulates an RRset like class that internally
+// uses RdataFields.  On construction it stores RDATA information in the
+// form of RdataFields fields.  Its toWire() method restores the data as
+// an RdataFields object for the rendering.
+class RdataFieldsStore {
+public:
+    RdataFieldsStore(ConstRdataPtr rdata) {
+        const RdataFields fields(*rdata);
+
+        nspecs_ = fields.getFieldCount();
+        spec_store_.resize(nspecs_ * sizeof(RdataFields::FieldSpec));
+        void* cp_spec = &spec_store_[0];
+        memcpy(cp_spec, fields.getFieldSpecData(), spec_store_.size());
+        spec_ptr_ = static_cast<RdataFields::FieldSpec*>(cp_spec);
+
+        data_length_ = fields.getDataLength();
+        data_store_.assign(fields.getData(), fields.getData() + data_length_);
+        data_ptr_ = &data_store_[0];
+    }
+    void toWire(MessageRenderer& renderer) const {
+        RdataFields(spec_ptr_, nspecs_,
+                    data_ptr_, data_length_).toWire(renderer);
+    }
+private:
+    vector<unsigned char> spec_store_;
+    const RdataFields::FieldSpec* spec_ptr_;
+    unsigned int nspecs_;
+    vector<uint8_t> data_store_;
+    const uint8_t* data_ptr_;
+    size_t data_length_;
+};
+
+// We wouldn't necessarily have to use a shared pointer, but it's easier
+// to use pointer-like values to adjust them with the RdataRenderBenchMark
+// template.
+typedef boost::shared_ptr<const RdataFieldsStore> ConstRdataFieldsStorePtr;
+
+void
+readInputFile(const char* const input_file, vector<ConstRdataPtr>& rdata_sets,
+              vector<ConstRdataFieldsStorePtr>& fields_sets)
+{
+    ifstream ifs;
+    ifs.open(input_file, ios_base::in);
+    if ((ifs.rdstate() & istream::failbit) != 0) {
+        cerr << "Failed to read input file: " << input_file << endl;
+        exit (1);
+    }
+    string line;
+    unsigned int linenum = 0;
+    while (getline(ifs, line), !ifs.eof()) {
+        ++linenum;
+        if (ifs.bad() || ifs.fail()) {
+            cerr << "Unexpected input at line " << linenum << endl;
+            exit (1);
+        }
+        if (line.empty() || line[0] == '#') {
+            continue;           // skip comment and blank lines
+        }
+        istringstream iss(line);
+        string rrclass_string, rrtype_string;
+        stringbuf rdatabuf;
+        iss >> rrclass_string >> rrtype_string >> &rdatabuf;
+        if (iss.bad() || iss.fail()) {
+            cerr << "Unexpected input at line " << linenum << endl;
+            exit (1);
+        }
+        ConstRdataPtr rdata = createRdata(RRType(rrtype_string),
+                                          RRClass(rrclass_string),
+                                          rdatabuf.str());
+        rdata_sets.push_back(rdata);
+        fields_sets.push_back(ConstRdataFieldsStorePtr(
+                                  new RdataFieldsStore(rdata)));
+    }
+    ifs.close();
+}
+
+void
+usage() {
+    cerr << "Usage: rdatafields_bench [-n iterations] input_file" << endl;
+    exit (1);
+}
+}
+
+int
+main(int argc, char* argv[]) {
+    int ch;
+    int iteration = 10000;
+    while ((ch = getopt(argc, argv, "n:")) != -1) {
+        switch (ch) {
+        case 'n':
+            iteration = atoi(optarg);
+            break;
+        case '?':
+        default:
+            usage();
+        }
+    }
+    argc -= optind;
+    argv += optind;
+    if (argc < 1) {
+        usage();
+    }
+    const char* const input_file = argv[0];
+
+    vector<ConstRdataPtr> rdata_sets;
+    vector<ConstRdataFieldsStorePtr> fields_sets;
+
+    readInputFile(input_file, rdata_sets, fields_sets);
+
+    cout << "Parameters:" << endl;
+    cout << "  Iterations: " << iteration << endl;
+    cout << "  Input File: " << input_file << endl;
+
+    typedef RdataRenderBenchMark<ConstRdataPtr> RdataBenchMark;
+    cout << "Benchmark for rendering with standard Rdata" << endl;
+    BenchMark<RdataBenchMark>(iteration, RdataBenchMark(rdata_sets));
+
+    typedef RdataRenderBenchMark<ConstRdataFieldsStorePtr> FieldsBenchMark;
+    cout << "Benchmark for rendering with RdataFields" << endl;
+    BenchMark<FieldsBenchMark>(iteration, FieldsBenchMark(fields_sets));
+
+    return (0);
+}