benchmark.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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 <string>
  15. #include <stdint.h>
  16. #ifndef BENCHMARK_H
  17. #define BENCHMARK_H
  18. /// @brief Micro-benchmark base class.
  19. ///
  20. /// This class represents an abstract DHCP database backend benchmark.
  21. /// It is not intended to be used directly, but serves as a common
  22. /// denominator for specific backend benchmarks that are derived from
  23. /// it. Currently there are at least 3 benchmarks implemented that
  24. /// take advantage of it:
  25. /// - MySQL (MySQL_uBenchmark)
  26. /// - SQLite (SQLite_uBenchmark)
  27. /// - memfile (memfile_uBenchmark)
  28. class uBenchmark {
  29. public:
  30. /// @brief the sole constructor, used by all derivated benchmarks
  31. ///
  32. /// @param iterations number of iterations of each step (insert, search,
  33. /// update, delete)
  34. /// @param dbname name of the database (that is backend-specific, either
  35. /// filename or DB name)
  36. /// @param sync sync or async test mode
  37. /// @param verbose should extra logging be enabled?
  38. /// @param host some backends (currently only MySQL) need this (optional)
  39. /// @param username some backends (currently only MySQL) need this (optional)
  40. /// @param pass some backends (currently only MySQL) need this (optional)
  41. uBenchmark(uint32_t iterations, const std::string& dbname,
  42. bool sync, bool verbose,
  43. const std::string& host = "",
  44. const std::string& username = "",
  45. const std::string& pass = "");
  46. /// @brief Prints version information about specific backend.
  47. ///
  48. /// The implementation is provided by the DB-specific class.
  49. virtual void printInfo() = 0;
  50. /// @brief Opens a connection to the database.
  51. ///
  52. /// The implementation is provided by the DB-specific class.
  53. virtual void connect() = 0;
  54. /// @brief Closes connection to the database.
  55. ///
  56. /// The implementation is provided by the DB-specific class.
  57. virtual void disconnect() = 0;
  58. /// @brief Benchmarks IPv4 address lease creation.
  59. ///
  60. /// That benchmark method will be called first.
  61. /// It is expected to create specific number of leases,
  62. /// as specified by \ref num_ parameter. Following
  63. /// methods (searchLease4Test(), updateLease4Test(),
  64. /// and deleteLease4Test()) assume that lease creation
  65. /// is successful. The benchmark is expected to create leases
  66. /// starting from BASE_ADDR4 and ending on BASE_ADDR4 + num_.
  67. ///
  68. /// The implementation is provided by the DB-specific class.
  69. virtual void createLease4Test() = 0;
  70. /// @brief Benchmarks IPv4 address lease search.
  71. ///
  72. /// This is the second benchmark in a series of four.
  73. /// It is called after createLease4Test(), so it expects that the
  74. /// database is populated with at least \ref num_ leases.
  75. /// It repeats search for a lease num_ times.
  76. ///
  77. /// The algorithm randomly picks a lease with \ref hitratio_ (typically 90%)
  78. /// chance of finding a lease. During typical DHCP operation the server
  79. /// sometimes wants to check if specific lease is assigned or not and the
  80. /// lease is sometimes not present (e.g. when randomly trying to pick a new
  81. /// lease for a new client or doing confirm). Although rather unlikely,
  82. /// cases when searching for non-existing leases may be more costly,
  83. /// thus should be modelled.
  84. ///
  85. /// The implementation is provided by the DB-specific class.
  86. virtual void searchLease4Test() = 0;
  87. /// @brief Benchmarks IPv4 address lease update.
  88. ///
  89. /// This is the third benchmark in a series of four.
  90. /// It is called after createLease4Test(), so it expects that the
  91. /// database is populated with at least \ref num_ leases.
  92. ///
  93. /// In a normal DHCP operation, search and update operations are used
  94. /// together, but for the benchmarking purposes they are executed
  95. /// separately here. Once a lease is found, it is being updated. Typically
  96. /// the update is just changing lease expiration timers, so that is what
  97. /// the test does. It exploits the fact that there are num_ leases
  98. /// in the database, so it picks randomly an address from
  99. /// BASE_ADDR4 ... BASE_ADDR4 + num_ range and has a guarantee for the lease
  100. /// to be present.
  101. ///
  102. /// The implementation is provided by the DB-specific class.
  103. virtual void updateLease4Test() = 0;
  104. /// @brief Benchmarks IPv4 address lease removal.
  105. ///
  106. /// This is the last benchmark in a series of four.
  107. /// It is called after createLease4Test(), so it expects that the
  108. /// database is populated with at least \ref num_ leases.
  109. ///
  110. /// It is expected to iteratively delete all num_ leases from
  111. /// the database.
  112. ///
  113. /// The implementation is provided by the DB-specific class.
  114. virtual void deleteLease4Test() = 0;
  115. /// @brief Utility function for reporting errors.
  116. ///
  117. /// Benchmarks should call that function when something goes wrong.
  118. /// details of the problem must be passed as a parameter. As the benchmark
  119. /// is not designed to recover from errors, reporting an error aborts
  120. /// benchmark execution.
  121. ///
  122. /// @param operation description of the operation that caused failure
  123. virtual void failure(const char* operation);
  124. /// @brief Prints elapsed time of a specific operation
  125. ///
  126. /// This method prints out elapsed time of a specific benchmark, together
  127. /// with additional statistics.
  128. ///
  129. /// @param operation name of the operation (usually create, search, update, delete)
  130. /// @param num number or iterations (used for statistics)
  131. /// @param before timestamp before execution
  132. /// @param after timestamp after execution
  133. void printClock(const std::string& operation, uint32_t num,
  134. const struct timespec& before,
  135. const struct timespec& after);
  136. /// @brief Main benchmark execution routine
  137. ///
  138. /// This method calls create, search, update and delete benchmarks
  139. /// and measures appropriate timestamps in ts_ table.
  140. ///
  141. /// @return 0 if the run was successful, negative value if detected errors
  142. int run();
  143. /// @brief parses command-line parameters
  144. ///
  145. /// This method parses command-line parameters and sets up appropriate
  146. /// values. It is ok to pass argc, argv from main() here.
  147. ///
  148. /// This method may not return if -h (help) was specified or invalid
  149. /// arguments are passed. Appropriate error and help will be displayed
  150. /// and the program will terminate.
  151. ///
  152. /// @param argc number of arguments
  153. /// @param argv array to the arguments
  154. void parseCmdline(int argc, char* const argv[]);
  155. protected:
  156. /// @brief prints out command-line help (list of parameters + version)
  157. void usage();
  158. /// @brief a wrapper around OS-specific method for getting time
  159. struct timespec getTime();
  160. /// Number of operations (e.g. insert lease num times)
  161. uint32_t num_;
  162. /// Synchronous or asynchronous mode?
  163. bool sync_;
  164. /// Should the test print out extra information?
  165. bool verbose_;
  166. // DB parameters
  167. std::string hostname_; // used by MySQL only
  168. std::string user_; // used by MySQL only
  169. std::string passwd_; // used by MySQL only
  170. std::string dbname_; // used by MySQL, SQLite and memfile
  171. /// @brief hit ratio for search test (must be between 0.0 and 1.0)
  172. ///
  173. /// This parameter is used in search benchmark. The formula causes the
  174. /// search to find something a lease in 90% cases of hit ratio is 0.9.
  175. float hitratio_;
  176. /// benchmarks must generate the leases starting from 1.0.0.0 address
  177. const static uint32_t BASE_ADDR4 = 0x01000000;
  178. /// five timestamps (1 at the beginning and 4 after each step)
  179. struct timespec ts_[5];
  180. /// should compiled statements be used?
  181. bool compiled_stmt_;
  182. };
  183. #endif