rdatarender_bench.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright (C) 2010 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 <iostream>
  15. #include <fstream>
  16. #include <string>
  17. #include <vector>
  18. #include <boost/shared_ptr.hpp>
  19. #include <bench/benchmark.h>
  20. #include <dns/buffer.h>
  21. #include <dns/messagerenderer.h>
  22. #include <dns/rdata.h>
  23. #include <dns/rdatafields.h>
  24. #include <dns/rrclass.h>
  25. #include <dns/rrtype.h>
  26. using namespace std;
  27. using namespace isc::bench;
  28. using namespace isc::dns;
  29. using namespace isc::dns::rdata;
  30. namespace {
  31. // This templated benchmark class is constructed with a vector of Rdata-like
  32. // (pointer) objects which should have a "toWire()" method. In its run(),
  33. // it calls toWire() for each element of the vector.
  34. template <typename T>
  35. class RdataRenderBenchMark {
  36. public:
  37. RdataRenderBenchMark(const vector<T>& dataset) :
  38. dataset_(dataset), buffer_(4096), renderer_(buffer_)
  39. {}
  40. unsigned int run() {
  41. typename vector<T>::const_iterator data;
  42. typename vector<T>::const_iterator data_end = dataset_.end();
  43. for (data = dataset_.begin(); data != data_end; ++data) {
  44. renderer_.clear();
  45. (*data)->toWire(renderer_);
  46. }
  47. return (dataset_.size());
  48. }
  49. private:
  50. const vector<T>& dataset_;
  51. OutputBuffer buffer_;
  52. MessageRenderer renderer_;
  53. };
  54. // This supplemental class emulates an RRset like class that internally
  55. // uses RdataFields. On construction it stores RDATA information in the
  56. // form of RdataFields fields. Its toWire() method restores the data as
  57. // an RdataFields object for the rendering.
  58. class RdataFieldsStore {
  59. public:
  60. RdataFieldsStore(ConstRdataPtr rdata) {
  61. const RdataFields fields(*rdata);
  62. nspecs_ = fields.getFieldCount();
  63. spec_store_.resize(nspecs_ * sizeof(RdataFields::FieldSpec));
  64. void* cp_spec = &spec_store_[0];
  65. memcpy(cp_spec, fields.getFieldSpecData(), spec_store_.size());
  66. spec_ptr_ = static_cast<RdataFields::FieldSpec*>(cp_spec);
  67. data_length_ = fields.getDataLength();
  68. data_store_.assign(fields.getData(), fields.getData() + data_length_);
  69. // Vector guarantees that the elements are stored in continuous array
  70. // in memory, so this is actually correct by the standard
  71. data_ptr_ = &data_store_[0];
  72. }
  73. void toWire(MessageRenderer& renderer) const {
  74. RdataFields(spec_ptr_, nspecs_,
  75. data_ptr_, data_length_).toWire(renderer);
  76. }
  77. private:
  78. vector<unsigned char> spec_store_;
  79. const RdataFields::FieldSpec* spec_ptr_;
  80. unsigned int nspecs_;
  81. vector<uint8_t> data_store_;
  82. const uint8_t* data_ptr_;
  83. size_t data_length_;
  84. };
  85. // We wouldn't necessarily have to use a shared pointer, but it's easier
  86. // to use pointer-like values to adjust them with the RdataRenderBenchMark
  87. // template.
  88. typedef boost::shared_ptr<const RdataFieldsStore> ConstRdataFieldsStorePtr;
  89. void
  90. readInputFile(const char* const input_file, vector<ConstRdataPtr>& rdata_sets,
  91. vector<ConstRdataFieldsStorePtr>& fields_sets)
  92. {
  93. ifstream ifs;
  94. ifs.open(input_file, ios_base::in);
  95. if ((ifs.rdstate() & istream::failbit) != 0) {
  96. cerr << "Failed to read input file: " << input_file << endl;
  97. exit (1);
  98. }
  99. string line;
  100. unsigned int linenum = 0;
  101. while (getline(ifs, line), !ifs.eof()) {
  102. ++linenum;
  103. if (ifs.bad() || ifs.fail()) {
  104. cerr << "Unexpected input at line " << linenum << endl;
  105. exit (1);
  106. }
  107. if (line.empty() || line[0] == '#') {
  108. continue; // skip comment and blank lines
  109. }
  110. istringstream iss(line);
  111. string rrclass_string, rrtype_string;
  112. stringbuf rdatabuf;
  113. iss >> rrclass_string >> rrtype_string >> &rdatabuf;
  114. if (iss.bad() || iss.fail()) {
  115. cerr << "Unexpected input at line " << linenum << endl;
  116. exit (1);
  117. }
  118. ConstRdataPtr rdata = createRdata(RRType(rrtype_string),
  119. RRClass(rrclass_string),
  120. rdatabuf.str());
  121. rdata_sets.push_back(rdata);
  122. fields_sets.push_back(ConstRdataFieldsStorePtr(
  123. new RdataFieldsStore(rdata)));
  124. }
  125. ifs.close();
  126. }
  127. void
  128. usage() {
  129. cerr << "Usage: rdatafields_bench [-n iterations] input_file" << endl;
  130. exit (1);
  131. }
  132. }
  133. int
  134. main(int argc, char* argv[]) {
  135. int ch;
  136. int iteration = 10000;
  137. while ((ch = getopt(argc, argv, "n:")) != -1) {
  138. switch (ch) {
  139. case 'n':
  140. iteration = atoi(optarg);
  141. break;
  142. case '?':
  143. default:
  144. usage();
  145. }
  146. }
  147. argc -= optind;
  148. argv += optind;
  149. if (argc < 1) {
  150. usage();
  151. }
  152. const char* const input_file = argv[0];
  153. vector<ConstRdataPtr> rdata_sets;
  154. vector<ConstRdataFieldsStorePtr> fields_sets;
  155. readInputFile(input_file, rdata_sets, fields_sets);
  156. cout << "Parameters:" << endl;
  157. cout << " Iterations: " << iteration << endl;
  158. cout << " Input File: " << input_file << endl;
  159. typedef RdataRenderBenchMark<ConstRdataPtr> RdataBenchMark;
  160. cout << "Benchmark for rendering with standard Rdata" << endl;
  161. BenchMark<RdataBenchMark>(iteration, RdataBenchMark(rdata_sets));
  162. typedef RdataRenderBenchMark<ConstRdataFieldsStorePtr> FieldsBenchMark;
  163. cout << "Benchmark for rendering with RdataFields" << endl;
  164. BenchMark<FieldsBenchMark>(iteration, FieldsBenchMark(fields_sets));
  165. return (0);
  166. }