message_renderer_bench.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <bench/benchmark.h>
  15. #include <dns/name.h>
  16. #include <dns/messagerenderer.h>
  17. #include <dns/oldmessagerenderer.h>
  18. #include <dns/expmessagerenderer.h>
  19. #include <cassert>
  20. #include <vector>
  21. using namespace std;
  22. using namespace isc::util;
  23. using namespace isc::bench;
  24. using namespace isc::dns;
  25. namespace {
  26. // This templated test performs rendering given set of names using
  27. // a given (templated) MessageRenderer implementation. We can check the
  28. // performance when we modify the renderer implementation by comparing the
  29. // old and new implementation for the same data.
  30. template <typename T>
  31. class MessageRendererBenchMark {
  32. public:
  33. MessageRendererBenchMark(const vector<Name>& names) :
  34. names_(names)
  35. {}
  36. unsigned int run() {
  37. renderer_.clear();
  38. vector<Name>::const_iterator it = names_.begin();
  39. const vector<Name>::const_iterator it_end = names_.end();
  40. for (; it != it_end; ++it) {
  41. renderer_.writeName(*it);
  42. }
  43. // Make sure truncation didn't accidentally happen.
  44. assert(!renderer_.isTruncated());
  45. return (names_.size());
  46. }
  47. private:
  48. T renderer_;
  49. const vector<Name>& names_;
  50. };
  51. //
  52. // Builtin benchmark data.
  53. //
  54. // This consists of all names contained in a response from a root server for
  55. // the query for "www.example.com" (as of this implementing).
  56. const char* const root_to_com_names[] = {
  57. // question section
  58. "www.example.com",
  59. // authority section
  60. "com", "a.gtld-servers.net", "com", "b.gtld-servers.net",
  61. "com", "c.gtld-servers.net", "com", "d.gtld-servers.net",
  62. "com", "e.gtld-servers.net", "com", "f.gtld-servers.net",
  63. "com", "g.gtld-servers.net", "com", "h.gtld-servers.net",
  64. "com", "i.gtld-servers.net", "com", "j.gtld-servers.net",
  65. "com", "k.gtld-servers.net", "com", "l.gtld-servers.net",
  66. "com", // owner name of DS
  67. "com", // owner name of RRSIG(DS)
  68. // additional section. a and b has both AAAA and A; others have A only.
  69. "a.gtld-servers.net", "a.gtld-servers.net",
  70. "b.gtld-servers.net", "b.gtld-servers.net",
  71. "c.gtld-servers.net", "d.gtld-servers.net", "e.gtld-servers.net",
  72. "f.gtld-servers.net", "g.gtld-servers.net", "h.gtld-servers.net",
  73. "i.gtld-servers.net", "j.gtld-servers.net", "k.gtld-servers.net",
  74. "l.gtld-servers.net", "m.gtld-servers.net",
  75. NULL
  76. };
  77. // Names contained a typical "NXDOMAIN" response: the question, the owner
  78. // name of SOA, and its MNAME and RNAME.
  79. const char* const example_nxdomain_names[] = {
  80. "www.example.com", "example.com", "ns.example.com", "root.example.com",
  81. NULL
  82. };
  83. // Names contained a typical "SERVFAIL" response: only the question.
  84. const char* const example_servfail_names[] = {
  85. "www.example.com", NULL
  86. };
  87. // An experimental "dumb" renderer for comparison. It doesn't do any name
  88. // compression. It simply ignores all setter method, returns a dummy value
  89. // for getter methods, and write names to the internal buffer as plain binary
  90. // data.
  91. class DumbMessageRenderer : public AbstractMessageRenderer {
  92. public:
  93. virtual void clear() {}
  94. virtual size_t getLengthLimit() const { return (512); }
  95. virtual void setLengthLimit(const size_t) {}
  96. virtual bool isTruncated() const { return (false); }
  97. virtual void setTruncated() {}
  98. virtual CompressMode getCompressMode() const { return (CASE_INSENSITIVE); }
  99. virtual void setCompressMode(const CompressMode) {}
  100. virtual void writeName(const Name& name, const bool = false) {
  101. name.toWire(getBuffer());
  102. }
  103. };
  104. void
  105. usage() {
  106. cerr << "Usage: message_renderer_bench [-n iterations]" << endl;
  107. exit (1);
  108. }
  109. }
  110. int
  111. main(int argc, char* argv[]) {
  112. int ch;
  113. int iteration = 100000;
  114. while ((ch = getopt(argc, argv, "n:")) != -1) {
  115. switch (ch) {
  116. case 'n':
  117. iteration = atoi(optarg);
  118. break;
  119. case '?':
  120. default:
  121. usage();
  122. }
  123. }
  124. argc -= optind;
  125. argv += optind;
  126. if (argc != 0) {
  127. usage();
  128. }
  129. cout << "Parameters:" << endl;
  130. cout << " Iterations: " << iteration << endl;
  131. typedef pair<const char* const*, string> DataSpec;
  132. vector<DataSpec> spec_list;
  133. spec_list.push_back(DataSpec(root_to_com_names, "(positive response)"));
  134. spec_list.push_back(DataSpec(example_nxdomain_names,
  135. "(NXDOMAIN response)"));
  136. spec_list.push_back(DataSpec(example_servfail_names,
  137. "(SERVFAIL response)"));
  138. for (vector<DataSpec>::const_iterator it = spec_list.begin();
  139. it != spec_list.end();
  140. ++it) {
  141. vector<Name> names;
  142. for (size_t i = 0; it->first[i] != NULL; ++i) {
  143. names.push_back(Name(it->first[i]));
  144. }
  145. typedef MessageRendererBenchMark<OldMessageRenderer>
  146. OldRendererBenchMark;
  147. cout << "Benchmark for old MessageRenderer " << it->second << endl;
  148. BenchMark<OldRendererBenchMark>(iteration,
  149. OldRendererBenchMark(names));
  150. typedef MessageRendererBenchMark<DumbMessageRenderer>
  151. DumbRendererBenchMark;
  152. cout << "Benchmark for dumb MessageRenderer " << it->second << endl;
  153. BenchMark<DumbRendererBenchMark>(iteration,
  154. DumbRendererBenchMark(names));
  155. typedef MessageRendererBenchMark<ExpMessageRenderer>
  156. ExpRendererBenchMark;
  157. cout << "Benchmark for experimental MessageRenderer " <<
  158. it->second << endl;
  159. BenchMark<ExpRendererBenchMark>(iteration,
  160. ExpRendererBenchMark(names));
  161. typedef MessageRendererBenchMark<MessageRenderer> RendererBenchMark;
  162. cout << "Benchmark for new MessageRenderer " << it->second << endl;
  163. BenchMark<RendererBenchMark>(iteration, RendererBenchMark(names));
  164. }
  165. return (0);
  166. }