Commit ea0c9765 authored by Franciszek Gorski's avatar Franciszek Gorski Committed by Tomek Mrugalski

[144-remove-obsolete-dns-benchmarks] Removing obsolete dns benchmarks in src/lib/dns/benchmarks

parent 093b3333
/message_renderer_bench
/rdatarender_bench
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
- 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_*.
# 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
# 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=
# 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
// 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);
}
// 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);
}
}
}
// 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:
// 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