1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
// Copyright (C) 2012 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 <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);
}
|