+++ /dev/null
-/message_renderer_bench
-/rdatarender_bench
+++ /dev/null
-AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-AM_CPPFLAGS += $(BOOST_INCLUDES)
-
-AM_CXXFLAGS = $(KEA_CXXFLAGS)
-
-if USE_STATIC_LINK
-AM_LDFLAGS = -static
-endif
-
-CLEANFILES = *.gcno *.gcda
-
-noinst_PROGRAMS = rdatarender_bench message_renderer_bench
-
-rdatarender_bench_SOURCES = rdatarender_bench.cc
-
-rdatarender_bench_LDADD = $(top_builddir)/src/lib/dns/libkea-dns++.la
-rdatarender_bench_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
-rdatarender_bench_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
-
-message_renderer_bench_SOURCES = message_renderer_bench.cc
-message_renderer_bench_SOURCES += oldmessagerenderer.h oldmessagerenderer.cc
-message_renderer_bench_LDADD = $(top_builddir)/src/lib/dns/libkea-dns++.la
-message_renderer_bench_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
-message_renderer_bench_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
+++ /dev/null
-- 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_*.
+++ /dev/null
-# 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
+++ /dev/null
-# 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=
+++ /dev/null
-# 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
+++ /dev/null
-// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <config.h>
-
-#include <bench/benchmark.h>
-
-#include <dns/name.h>
-#include <dns/labelsequence.h>
-#include <dns/messagerenderer.h>
-#include <oldmessagerenderer.h>
-
-#include <cassert>
-#include <vector>
-
-using namespace std;
-using namespace isc::util;
-using namespace isc::bench;
-using namespace isc::dns;
-
-namespace {
-// This templated test performs rendering given set of names using
-// a given (templated) MessageRenderer implementation. We can check the
-// performance when we modify the renderer implementation by comparing the
-// old and new implementation for the same data.
-template <typename T>
-class MessageRendererBenchMark {
-public:
- MessageRendererBenchMark(const vector<Name>& names) :
- renderer_(NULL),
- names_(names)
- {}
- ~MessageRendererBenchMark() {
- delete renderer_;
- }
- unsigned int run() {
- if (renderer_ == NULL) {
- renderer_ = new T();
- }
- renderer_->clear();
- vector<Name>::const_iterator it = names_.begin();
- const vector<Name>::const_iterator it_end = names_.end();
- for (; it != it_end; ++it) {
- renderer_->writeName(*it);
- }
- // Make sure truncation didn't accidentally happen.
- assert(!renderer_->isTruncated());
- return (names_.size());
- }
-private:
- T* renderer_; // It's pointer, so we won't need to copy it.
- const vector<Name>& names_;
-};
-
-//
-// Builtin benchmark data.
-//
-// This consists of all names contained in a response from a root server for
-// the query for "www.example.com" (as of this implementing).
-const char* const root_to_com_names[] = {
- // question section
- "www.example.com",
- // authority section
- "com", "a.gtld-servers.net", "com", "b.gtld-servers.net",
- "com", "c.gtld-servers.net", "com", "d.gtld-servers.net",
- "com", "e.gtld-servers.net", "com", "f.gtld-servers.net",
- "com", "g.gtld-servers.net", "com", "h.gtld-servers.net",
- "com", "i.gtld-servers.net", "com", "j.gtld-servers.net",
- "com", "k.gtld-servers.net", "com", "l.gtld-servers.net",
- "com", // owner name of DS
- "com", // owner name of RRSIG(DS)
- // additional section. a and b has both AAAA and A; others have A only.
- "a.gtld-servers.net", "a.gtld-servers.net",
- "b.gtld-servers.net", "b.gtld-servers.net",
- "c.gtld-servers.net", "d.gtld-servers.net", "e.gtld-servers.net",
- "f.gtld-servers.net", "g.gtld-servers.net", "h.gtld-servers.net",
- "i.gtld-servers.net", "j.gtld-servers.net", "k.gtld-servers.net",
- "l.gtld-servers.net", "m.gtld-servers.net",
- NULL
-};
-
-// Names contained a typical "NXDOMAIN" response: the question, the owner
-// name of SOA, and its MNAME and RNAME.
-const char* const example_nxdomain_names[] = {
- "www.example.com", "example.com", "ns.example.com", "root.example.com",
- NULL
-};
-
-// Names contained a typical "SERVFAIL" response: only the question.
-const char* const example_servfail_names[] = {
- "www.example.com", NULL
-};
-
-// An experimental "dumb" renderer for comparison. It doesn't do any name
-// compression. It simply ignores all setter method, returns a dummy value
-// for getter methods, and write names to the internal buffer as plain binary
-// data.
-class DumbMessageRenderer : public AbstractMessageRenderer {
-public:
- virtual void clear() {}
- virtual size_t getLengthLimit() const { return (512); }
- virtual void setLengthLimit(const size_t) {}
- virtual bool isTruncated() const { return (false); }
- virtual void setTruncated() {}
- virtual CompressMode getCompressMode() const { return (CASE_INSENSITIVE); }
- virtual void setCompressMode(const CompressMode) {}
- virtual void writeName(const Name& name, const bool = false) {
- name.toWire(getBuffer());
- }
- virtual void writeName(const LabelSequence&, const bool) {
- // We shouldn't use this version of writeName (and we internally
- // control it, so we simply assert it here)
- assert(false);
- }
-};
-
-void
-usage() {
- cerr << "Usage: message_renderer_bench [-n iterations]" << endl;
- exit (1);
-}
-}
-
-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;
- case '?':
- default:
- usage();
- }
- }
- argc -= optind;
- if (argc != 0) {
- usage();
- }
-
- cout << "Parameters:" << endl;
- cout << " Iterations: " << iteration << endl;
-
- typedef pair<const char* const*, string> DataSpec;
- vector<DataSpec> spec_list;
- spec_list.push_back(DataSpec(root_to_com_names, "(positive response)"));
- spec_list.push_back(DataSpec(example_nxdomain_names,
- "(NXDOMAIN response)"));
- spec_list.push_back(DataSpec(example_servfail_names,
- "(SERVFAIL response)"));
- for (vector<DataSpec>::const_iterator it = spec_list.begin();
- it != spec_list.end();
- ++it) {
- vector<Name> names;
- for (size_t i = 0; it->first[i] != NULL; ++i) {
- names.push_back(Name(it->first[i]));
- }
-
- typedef MessageRendererBenchMark<OldMessageRenderer>
- OldRendererBenchMark;
- cout << "Benchmark for old MessageRenderer " << it->second << endl;
- BenchMark<OldRendererBenchMark>(iteration,
- OldRendererBenchMark(names));
-
- typedef MessageRendererBenchMark<DumbMessageRenderer>
- DumbRendererBenchMark;
- cout << "Benchmark for dumb MessageRenderer " << it->second << endl;
- BenchMark<DumbRendererBenchMark>(iteration,
- DumbRendererBenchMark(names));
-
- typedef MessageRendererBenchMark<MessageRenderer> RendererBenchMark;
- cout << "Benchmark for new MessageRenderer " << it->second << endl;
- BenchMark<RendererBenchMark>(iteration, RendererBenchMark(names));
- }
-
- return (0);
-}
+++ /dev/null
-// Copyright (C) 2009-2015 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <config.h>
-
-#include <exceptions/exceptions.h>
-#include <util/buffer.h>
-#include <dns/name.h>
-#include <dns/labelsequence.h>
-#include <oldmessagerenderer.h>
-
-#include <cctype>
-#include <cassert>
-#include <set>
-
-using namespace isc::util;
-
-namespace isc {
-namespace dns {
-
-namespace { // hide internal-only names from the public namespaces
-///
-/// \brief The \c NameCompressNode class represents a pointer to a name
-/// rendered in the internal buffer for the \c MessageRendererImpl object.
-///
-/// A \c MessageRendererImpl object maintains a set of the \c NameCompressNode
-/// objects, and searches the set for the position of the longest match
-/// (ancestor) name against each new name to be rendered into the buffer.
-struct NameCompressNode {
- NameCompressNode(const OldMessageRenderer& renderer,
- const OutputBuffer& buffer, const size_t pos,
- const size_t len) :
- renderer_(renderer), buffer_(buffer), pos_(pos), len_(len) {}
- /// The renderer that performs name compression using the node.
- /// This is kept in each node to detect the compression mode
- /// (case-sensitive or not) in the comparison functor (\c NameCompare).
- const OldMessageRenderer& renderer_;
- /// The buffer in which the corresponding name is rendered.
- const OutputBuffer& buffer_;
- /// The position (offset from the beginning) in the buffer where the
- /// name starts.
- uint16_t pos_;
- /// The length of the corresponding name.
- uint16_t len_;
-};
-
-///
-/// \brief The \c NameCompare class is a functor that gives ordering among
-/// \c NameCompressNode objects stored in \c MessageRendererImpl::nodeset_.
-///
-/// Its only public method as a functor, \c operator(), gives the ordering
-/// between two \c NameCompressNode objects in terms of equivalence, that is,
-/// returns whether one is "less than" the other.
-/// For our purpose we only need to distinguish two different names, so the
-/// ordering is different from the canonical DNS name order used in DNSSEC;
-/// basically, it gives the case-insensitive ordering of the two names as their
-/// textual representation.
-struct NameCompare : public std::binary_function<NameCompressNode,
- NameCompressNode,
- bool> {
- ///
- /// Returns true if n1 < n2 as a result of case-insensitive comparison;
- /// otherwise return false.
- ///
- /// The name corresponding to \c n1 or \c n2 may be compressed, in which
- /// case we must follow the compression pointer in the associated buffer.
- /// The helper private method \c nextPosition() gives the position in the
- /// buffer for the next character, taking into account compression.
- ///
- bool operator()(const NameCompressNode& n1,
- const NameCompressNode& n2) const
- {
- if (n1.len_ < n2.len_) {
- return (true);
- } else if (n1.len_ > n2.len_) {
- return (false);
- }
-
- const bool case_sensitive =
- (n1.renderer_.getCompressMode() == OldMessageRenderer::CASE_SENSITIVE);
-
- uint16_t pos1 = n1.pos_;
- uint16_t pos2 = n2.pos_;
- uint16_t l1 = 0;
- uint16_t l2 = 0;
- for (uint16_t i = 0; i < n1.len_; i++, pos1++, pos2++) {
- pos1 = nextPosition(n1.buffer_, pos1, l1);
- pos2 = nextPosition(n2.buffer_, pos2, l2);
- if (case_sensitive) {
- if (n1.buffer_[pos1] < n2.buffer_[pos2]) {
- return (true);
- } else if (n1.buffer_[pos1] > n2.buffer_[pos2]) {
- return (false);
- }
- } else {
- if (tolower(n1.buffer_[pos1]) < tolower(n2.buffer_[pos2])) {
- return (true);
- } else if (tolower(n1.buffer_[pos1]) >
- tolower(n2.buffer_[pos2])) {
- return (false);
- }
- }
- }
-
- return (false);
- }
-
-private:
- uint16_t nextPosition(const OutputBuffer& buffer,
- uint16_t pos, uint16_t& llen) const
- {
- if (llen == 0) {
- size_t i = 0;
-
- while ((buffer[pos] & Name::COMPRESS_POINTER_MARK8) ==
- Name::COMPRESS_POINTER_MARK8) {
- pos = (buffer[pos] & ~Name::COMPRESS_POINTER_MARK8) *
- 256 + buffer[pos + 1];
-
- // This loop should stop as long as the buffer has been
- // constructed validly and the search/insert argument is based
- // on a valid name, which is an assumption for this class.
- // But we'll abort if a bug could cause an infinite loop.
- i += 2;
- assert(i < Name::MAX_WIRE);
- }
- llen = buffer[pos];
- } else {
- --llen;
- }
- return (pos);
- }
-};
-}
-
-///
-/// \brief The \c MessageRendererImpl class is the actual implementation of
-/// \c MessageRenderer.
-///
-/// The implementation is hidden from applications. We can refer to specific
-/// members of this class only within the implementation source file.
-///
-struct OldMessageRenderer::MessageRendererImpl {
- /// \brief Constructor from an output buffer.
- ///
- MessageRendererImpl() :
- nbuffer_(Name::MAX_WIRE), msglength_limit_(512),
- truncated_(false), compress_mode_(OldMessageRenderer::CASE_INSENSITIVE)
- {}
- /// A local working buffer to convert each given name into wire format.
- /// This could be a local variable of the \c writeName() method, but
- /// we keep it in the class so that we can reuse it and avoid construction
- /// overhead.
- OutputBuffer nbuffer_;
- /// A set of compression pointers.
- std::set<NameCompressNode, NameCompare> nodeset_;
- /// The maximum length of rendered data that can fit without
- /// truncation.
- uint16_t msglength_limit_;
- /// A boolean flag that indicates truncation has occurred while rendering
- /// the data.
- bool truncated_;
- /// The name compression mode.
- CompressMode compress_mode_;
-};
-
-OldMessageRenderer::OldMessageRenderer() :
- AbstractMessageRenderer(),
- impl_(new MessageRendererImpl)
-{}
-
-OldMessageRenderer::~OldMessageRenderer() {
- delete impl_;
-}
-
-void
-OldMessageRenderer::clear() {
- AbstractMessageRenderer::clear();
- impl_->nbuffer_.clear();
- impl_->nodeset_.clear();
- impl_->msglength_limit_ = 512;
- impl_->truncated_ = false;
- impl_->compress_mode_ = CASE_INSENSITIVE;
-}
-
-size_t
-OldMessageRenderer::getLengthLimit() const {
- return (impl_->msglength_limit_);
-}
-
-void
-OldMessageRenderer::setLengthLimit(const size_t len) {
- impl_->msglength_limit_ = len;
-}
-
-bool
-OldMessageRenderer::isTruncated() const {
- return (impl_->truncated_);
-}
-
-void
-OldMessageRenderer::setTruncated() {
- impl_->truncated_ = true;
-}
-
-OldMessageRenderer::CompressMode
-OldMessageRenderer::getCompressMode() const {
- return (impl_->compress_mode_);
-}
-
-void
-OldMessageRenderer::setCompressMode(const CompressMode mode) {
- impl_->compress_mode_ = mode;
-}
-
-void
-OldMessageRenderer::writeName(const Name& name, const bool compress) {
- impl_->nbuffer_.clear();
- name.toWire(impl_->nbuffer_);
-
- unsigned int i;
- std::set<NameCompressNode, NameCompare>::const_iterator notfound =
- impl_->nodeset_.end();
- std::set<NameCompressNode, NameCompare>::const_iterator n = notfound;
-
- // Find the longest ancestor name in the rendered set that matches the
- // given name.
- for (i = 0; i < impl_->nbuffer_.getLength(); i += impl_->nbuffer_[i] + 1) {
- // skip the trailing null label
- if (impl_->nbuffer_[i] == 0) {
- continue;
- }
- n = impl_->nodeset_.find(NameCompressNode(*this, impl_->nbuffer_, i,
- impl_->nbuffer_.getLength() -
- i));
- if (n != notfound) {
- break;
- }
- }
-
- // Record the current offset before extending the buffer.
- const size_t offset = getLength();
- // Write uncompress part...
- writeData(impl_->nbuffer_.getData(),
- compress ? i : impl_->nbuffer_.getLength());
- if (compress && n != notfound) {
- // ...and compression pointer if available.
- uint16_t pointer = (*n).pos_;
- pointer |= Name::COMPRESS_POINTER_MARK16;
- writeUint16(pointer);
- }
-
- // Finally, add to the set the newly rendered name and its ancestors that
- // have not been in the set.
- for (unsigned int j = 0; j < i; j += impl_->nbuffer_[j] + 1) {
- if (impl_->nbuffer_[j] == 0) {
- continue;
- }
- if (offset + j > Name::MAX_COMPRESS_POINTER) {
- break;
- }
- impl_->nodeset_.insert(NameCompressNode(*this, getBuffer(),
- offset + j,
- impl_->nbuffer_.getLength() -
- j));
- }
-}
-
-void
-OldMessageRenderer::writeName(const LabelSequence&, const bool) {
- // We shouldn't use this version of writeName (and we internally
- // control it, so we simply assert it here)
- assert(false);
-}
-
-}
-}
+++ /dev/null
-// Copyright (C) 2009-2015 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef OLDMESSAGERENDERER_H
-#define OLDMESSAGERENDERER_H 1
-
-//
-// This is a copy of an older version of MessageRenderer class. It is kept
-// here to provide a benchmark target.
-//
-
-#include <dns/messagerenderer.h>
-
-namespace isc {
-namespace dns {
-
-class OldMessageRenderer : public AbstractMessageRenderer {
-public:
- using AbstractMessageRenderer::CASE_INSENSITIVE;
- using AbstractMessageRenderer::CASE_SENSITIVE;
-
- /// \brief Constructor from an output buffer.
- OldMessageRenderer();
-
- virtual ~OldMessageRenderer();
- virtual bool isTruncated() const;
- virtual size_t getLengthLimit() const;
- virtual CompressMode getCompressMode() const;
- virtual void setTruncated();
- virtual void setLengthLimit(size_t len);
- virtual void setCompressMode(CompressMode mode);
- virtual void clear();
- virtual void writeName(const Name& name, bool compress = true);
- virtual void writeName(const LabelSequence& labels, bool compress);
-private:
- struct MessageRendererImpl;
- MessageRendererImpl* impl_;
-};
-}
-}
-#endif // OLDMESSAGERENDERER_H
-
-// Local Variables:
-// mode: c++
-// End:
+++ /dev/null
-// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <config.h>
-
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <vector>
-
-#include <boost/shared_ptr.hpp>
-
-#include <bench/benchmark.h>
-
-#include <util/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;
-using isc::util::OutputBuffer;
-
-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),
- renderer_(NULL)
- {}
- ~RdataRenderBenchMark() {
- delete renderer_;
- }
- unsigned int run() {
- if (renderer_ == NULL) {
- renderer_ = new MessageRenderer();
- }
- 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_;
- // Just-in-time initialized pointer, so no copy
- 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);
-
- spec_size_ = fields.getFieldSpecDataSize();
- spec_store_.resize(spec_size_);
- void* cp_spec = &spec_store_[0];
- memcpy(cp_spec, fields.getFieldSpecData(), spec_store_.size());
- spec_ptr_ = cp_spec;
-
- data_length_ = fields.getDataLength();
- data_store_.resize(data_length_);
- void* cp_data = &data_store_[0];
- memcpy(cp_data, fields.getData(), data_store_.size());
- // Vector guarantees that the elements are stored in continuous array
- // in memory, so this is actually correct by the standard
- data_ptr_ = cp_data;
- }
- void toWire(MessageRenderer& renderer) const {
- RdataFields(spec_ptr_, spec_size_,
- data_ptr_, data_length_).toWire(renderer);
- }
-private:
- vector<unsigned char> spec_store_;
- vector<unsigned char> data_store_;
- const void* spec_ptr_;
- const void* data_ptr_;
- unsigned int spec_size_;
- 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);
-}