benchmark.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 <iostream>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <boost/lexical_cast.hpp>
  18. #include "benchmark.h"
  19. // The following headers are for getting precise time (clock_gettime on Linux or that mac os thingie)
  20. #include <time.h>
  21. #include <sys/time.h>
  22. #ifdef __MACH__
  23. #include <mach/clock.h>
  24. #include <mach/mach.h>
  25. #endif
  26. using namespace std;
  27. uBenchmark::uBenchmark(uint32_t iterations, const std::string& dbname,
  28. bool sync /*= false*/, bool verbose /*= true*/,
  29. const std::string& host /* = "" */,
  30. const std::string& user /* = "" */,
  31. const std::string& pass /* = "" */)
  32. :num_(iterations), sync_(sync), verbose_(verbose),
  33. hostname_(host), user_(user), passwd_(pass), dbname_(dbname),
  34. hitratio_(0.9f), compiled_stmt_(true)
  35. {
  36. /// @todo: make compiled statements a configurable parameter
  37. /// @todo: convert hitratio_ to user-configurable parameter
  38. memset(ts_, 0, sizeof(ts_));
  39. }
  40. void uBenchmark::usage() {
  41. cout << "This is a benchmark designed to measure expected performance" << endl;
  42. cout << "of several backends. This backend identifies itself as:" << endl;
  43. printInfo();
  44. cout << endl << "Possible command-line parameters:" << endl;
  45. cout << " -h - help (you are reading this)" << endl;
  46. cout << " -m hostname - specifies MySQL server to connect (MySQL backend only)" << endl;
  47. cout << " -u username - specifies MySQL user name (MySQL backend only)" << endl;
  48. cout << " -p password - specifies MySQL passwod (MySQL backend only)" << endl;
  49. cout << " -f name - database or filename (MySQL, SQLite and memfile)" << endl;
  50. cout << " -n integer - number of test iterations (MySQL, SQLite and memfile)" << endl;
  51. cout << " -s yes|no - synchronous/asynchronous operation (MySQL, SQLite and memfile)" << endl;
  52. cout << " -v yes|no - verbose mode (MySQL, SQLite and memfile)" << endl;
  53. cout << " -c yes|no - compiled statements (MySQL and SQLite)" << endl;
  54. exit(EXIT_FAILURE);
  55. }
  56. void uBenchmark::parseCmdline(int argc, char* const argv[]) {
  57. int ch;
  58. while ((ch = getopt(argc, argv, "hm:u:p:f:n:s:v:c:")) != -1) {
  59. switch (ch) {
  60. case 'h':
  61. usage();
  62. case 'm':
  63. hostname_ = string(optarg);
  64. break;
  65. case 'u':
  66. user_ = string(optarg);
  67. break;
  68. case 'p':
  69. passwd_ = string(optarg);
  70. break;
  71. case 'f':
  72. dbname_ = string(optarg);
  73. break;
  74. case 'n':
  75. try {
  76. num_ = boost::lexical_cast<unsigned int>(optarg);
  77. } catch (const boost::bad_lexical_cast &) {
  78. cerr << "Failed to parse number of iterations (-n option):"
  79. << optarg << endl;
  80. usage();
  81. }
  82. break;
  83. case 'c':
  84. compiled_stmt_ = !strcasecmp(optarg, "yes") || !strcmp(optarg, "1");
  85. break;
  86. case 's':
  87. sync_ = !strcasecmp(optarg, "yes") || !strcmp(optarg, "1");
  88. break;
  89. case 'v':
  90. verbose_ = !strcasecmp(optarg, "yes") || !strcmp(optarg, "1");
  91. break;
  92. default:
  93. usage();
  94. }
  95. }
  96. }
  97. void uBenchmark::failure(const char* operation) {
  98. cout << "Error during " << operation << endl;
  99. throw string(operation);
  100. }
  101. void uBenchmark::printClock(const std::string& operation, uint32_t num,
  102. const struct timespec& before,
  103. const struct timespec& after) {
  104. long int tv_sec = after.tv_sec - before.tv_sec;
  105. long int tv_nsec = after.tv_nsec - before.tv_nsec;
  106. if (tv_nsec < 0) {
  107. tv_sec--;
  108. tv_nsec += 1000000000; // 10^9
  109. }
  110. double oneoper = (tv_nsec/1000 + tv_sec*1000000)/num;
  111. cout << operation << " repeated " << num << " times took "
  112. << tv_sec << " s, " << tv_nsec/1000 << " us, 1 operation took "
  113. << oneoper << "us (or " << (1000000/oneoper) << " oper/sec)" << endl;
  114. }
  115. int uBenchmark::run() {
  116. cout << "Starting test. Parameters:" << endl
  117. << "Number of iterations : " << num_ << endl
  118. << "Sync/async : " << (sync_ ? "sync" : "async") << endl
  119. << "Verbose : " << (verbose_ ? "verbose" : "quiet") << endl
  120. << "Compiled statements : " << (compiled_stmt_ ? "yes": "no") << endl
  121. << "Database name : " << dbname_ << endl
  122. << "MySQL hostname : " << hostname_ << endl
  123. << "MySQL username : " << user_ << endl
  124. << "MySQL password : " << passwd_ << endl << endl;
  125. srandom(time(NULL));
  126. try {
  127. connect();
  128. ts_[0] = getTime();
  129. createLease4Test();
  130. ts_[1] = getTime();
  131. searchLease4Test();
  132. ts_[2] = getTime();
  133. updateLease4Test();
  134. ts_[3] = getTime();
  135. deleteLease4Test();
  136. ts_[4] = getTime();
  137. disconnect();
  138. } catch (const std::string& e) {
  139. cout << "Failed: " << e << endl;
  140. return (-1);
  141. }
  142. printClock("Create leases4", num_, ts_[0], ts_[1]);
  143. printClock("Search leases4", num_, ts_[1], ts_[2]);
  144. printClock("Update leases4", num_, ts_[2], ts_[3]);
  145. printClock("Delete leases4", num_, ts_[3], ts_[4]);
  146. return (0);
  147. }
  148. struct timespec uBenchmark::getTime() {
  149. struct timespec ts;
  150. #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
  151. clock_serv_t cclock;
  152. mach_timespec_t mts;
  153. host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
  154. clock_get_time(cclock, &mts);
  155. mach_port_deallocate(mach_task_self(), cclock);
  156. ts.tv_sec = mts.tv_sec;
  157. ts.tv_nsec = mts.tv_nsec;
  158. #else
  159. clock_gettime(CLOCK_REALTIME, &ts);
  160. #endif
  161. return ts;
  162. }