rdatarender_bench.cc 6.1 KB

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