mysql_ubench.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  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 <sstream>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <time.h>
  20. #include <mysql.h>
  21. #include "benchmark.h"
  22. #include "mysql_ubench.h"
  23. using namespace std;
  24. MySQL_uBenchmark::MySQL_uBenchmark(const string& hostname, const string& user,
  25. const string& pass, const string& db,
  26. uint32_t num_iterations, bool sync,
  27. bool verbose)
  28. :uBenchmark(num_iterations, db, sync, verbose, hostname, user, pass),
  29. conn_(NULL) {
  30. }
  31. void MySQL_uBenchmark::failure(const char* operation) {
  32. stringstream tmp;
  33. tmp << "Error " << mysql_errno(conn_) << " during " << operation
  34. << ": " << mysql_error(conn_);
  35. throw tmp.str();
  36. }
  37. void MySQL_uBenchmark::connect() {
  38. conn_ = mysql_init(NULL);
  39. if (!conn_) {
  40. failure("initializing MySQL library");
  41. } else {
  42. cout << "MySQL library init successful." << endl;
  43. }
  44. if (!mysql_real_connect(conn_, hostname_.c_str(), user_.c_str(),
  45. passwd_.c_str(), dbname_.c_str(), 0, NULL, 0)) {
  46. failure("connecting to MySQL server");
  47. } else {
  48. cout << "MySQL connection established." << endl;
  49. }
  50. string q = "delete from lease4;";
  51. if (mysql_real_query(conn_, q.c_str(), strlen(q.c_str()))) {
  52. failure("dropping old lease4 entries.");
  53. }
  54. q = "ALTER TABLE lease4 engine=";
  55. if (sync_) {
  56. q += "InnoDB";
  57. } else {
  58. q += "MyISAM";
  59. }
  60. if (mysql_query(conn_, q.c_str())) {
  61. q = "Failed to run query:" + q;
  62. failure(q.c_str());
  63. }
  64. }
  65. void MySQL_uBenchmark::disconnect() {
  66. if (!conn_) {
  67. throw "NULL MySQL connection pointer.";
  68. }
  69. mysql_close(conn_);
  70. conn_ = NULL;
  71. }
  72. void MySQL_uBenchmark::createLease4Test() {
  73. if (!conn_) {
  74. throw "Not connected to MySQL server.";
  75. }
  76. uint32_t addr = BASE_ADDR4; // Let's start with 1.0.0.0 address
  77. char hwaddr[20];
  78. size_t hwaddr_len = 20; // Not a real field
  79. char client_id[128];
  80. size_t client_id_len = 128;
  81. uint32_t valid_lft = 1000; // We can use the same value for all leases
  82. uint32_t recycle_time = 7; // not supported in any foresable future,
  83. char cltt[48]; // timestamp (specified as text)
  84. size_t cltt_len;
  85. sprintf(cltt, "2012-07-11 15:43:00");
  86. cltt_len = strlen(cltt);
  87. uint32_t pool_id = 1000; // Let's use pool-ids greater than zero
  88. bool fixed = false;
  89. char hostname[] = "foo"; // Will generate it dynamically
  90. size_t hostname_len;
  91. hostname_len = strlen(hostname);
  92. bool fqdn_fwd = true; // Let's pretend to do AAAA update
  93. bool fqdn_rev = true; // Let's pretend to do PTR update
  94. cout << "CREATE: ";
  95. for (uint8_t i = 0; i < hwaddr_len; i++) {
  96. hwaddr[i] = 'A' + i; // let's make hwaddr consisting of letters
  97. }
  98. hwaddr[19] = 0; // make it is null-terminated
  99. for (uint8_t i = 0; i < client_id_len; i++) {
  100. client_id[i] = 33 + i; // 33 is being the first, non whitespace
  101. // printable ASCII character
  102. }
  103. client_id[127] = 0; // make it is null-terminated
  104. MYSQL_STMT * stmt = NULL;
  105. MYSQL_BIND bind[11]; // 11 parameters in the insert statement
  106. if (compiled_stmt_) {
  107. // create a statement once
  108. stmt = mysql_stmt_init(conn_);
  109. if (!stmt) {
  110. failure("Unable to create compiled statement, mysql_stmt_init() failed");
  111. }
  112. const char * statement = "INSERT INTO lease4(addr,hwaddr,client_id,"
  113. "valid_lft,recycle_time,cltt,pool_id,fixed,hostname,"
  114. "fqdn_fwd,fqdn_rev) VALUES(?,?,?,?,?,?,?,?,?,?,?)";
  115. if (mysql_stmt_prepare(stmt, statement, strlen(statement) )) {
  116. failure("Failed to prepare statement, mysql_stmt_prepare() returned non-zero");
  117. }
  118. int param_cnt = mysql_stmt_param_count(stmt);
  119. if (param_cnt != 11) {
  120. failure("Parameter count sanity check failed.");
  121. }
  122. memset(bind, 0, sizeof(bind));
  123. // 1st parameter: IPv4 address
  124. bind[0].buffer_type = MYSQL_TYPE_LONG;
  125. bind[0].buffer = (&addr);
  126. bind[0].is_null = 0;
  127. bind[0].length = 0;
  128. // 2nd parameter: Hardware address
  129. bind[1].buffer_type = MYSQL_TYPE_VARCHAR;
  130. bind[1].buffer = hwaddr;
  131. bind[1].buffer_length = hwaddr_len;
  132. bind[1].is_null = 0;
  133. bind[1].length = &hwaddr_len;
  134. // 3rd parameter: Client-id
  135. bind[2].buffer_type = MYSQL_TYPE_VARCHAR;
  136. bind[2].buffer = client_id;
  137. bind[2].buffer_length = client_id_len;
  138. bind[2].is_null = 0;
  139. bind[2].length = &client_id_len;
  140. // 4th parameter: valid-lifetime
  141. bind[3].buffer_type = MYSQL_TYPE_LONG;
  142. bind[3].buffer = (&valid_lft);
  143. bind[3].is_null = 0;
  144. bind[3].length = 0;
  145. // 5th parameter: recycle-time
  146. bind[4].buffer_type = MYSQL_TYPE_LONG;
  147. bind[4].buffer = (&recycle_time);
  148. bind[4].is_null = 0;
  149. bind[4].length = 0;
  150. // 6th parameter: cltt
  151. bind[5].buffer_type = MYSQL_TYPE_TIMESTAMP;
  152. bind[5].buffer = cltt;
  153. bind[2].buffer_length = cltt_len;
  154. bind[5].is_null = 0;
  155. bind[5].length = &cltt_len;
  156. // 7th parameter: pool-id
  157. bind[6].buffer_type = MYSQL_TYPE_LONG;
  158. bind[6].buffer = &pool_id;
  159. bind[6].is_null = 0;
  160. bind[6].length = 0;
  161. // 8th parameter: fixed
  162. bind[7].buffer_type = MYSQL_TYPE_TINY;
  163. bind[7].buffer = &fixed;
  164. bind[7].is_null = 0;
  165. bind[7].length = 0;
  166. // 9th parameter: hostname
  167. bind[8].buffer_type = MYSQL_TYPE_VARCHAR;
  168. bind[8].buffer = hostname;
  169. bind[8].buffer_length = strlen(hostname);
  170. bind[8].is_null = 0;
  171. bind[8].length = &hostname_len;
  172. // 10th parameter: fqdn_fwd
  173. bind[9].buffer_type = MYSQL_TYPE_TINY;
  174. bind[9].buffer = &fqdn_fwd;
  175. bind[9].is_null = 0;
  176. bind[9].length = 0;
  177. // 11th parameter: fqdn_rev
  178. bind[10].buffer_type = MYSQL_TYPE_TINY;
  179. bind[10].buffer = &fqdn_rev;
  180. bind[10].is_null = 0;
  181. bind[10].length = 0;
  182. }
  183. for (uint32_t i = 0; i < num_; i++) {
  184. sprintf(cltt, "2012-07-11 15:43:%02d", i % 60);
  185. addr++;
  186. if (!compiled_stmt_) {
  187. // the first address is 1.0.0.0.
  188. char query[2000], * end;
  189. strcpy(query, "INSERT INTO lease4(addr,hwaddr,client_id,"
  190. "valid_lft,recycle_time,cltt,pool_id,fixed,hostname,"
  191. "fqdn_fwd,fqdn_rev) VALUES(");
  192. end = query + strlen(query);
  193. end += sprintf(end, "%u,\'", addr);
  194. end += mysql_real_escape_string(conn_, end, hwaddr, hwaddr_len);
  195. end += sprintf(end,"\',\'");
  196. end += mysql_real_escape_string(conn_, end, client_id, client_id_len);
  197. end += sprintf(end, "\',%d,%d,'%s',%d,%s,\'%s\',%s,%s);",
  198. valid_lft, recycle_time, cltt,
  199. pool_id, (fixed?"true":"false"), hostname,
  200. (fqdn_fwd?"true":"false"), (fqdn_rev?"true":"false"));
  201. // lease_id field is set automatically
  202. // options and comments fields are not set
  203. unsigned int len = end - query;
  204. if (mysql_real_query(conn_, query, len)) {
  205. // something failed.
  206. failure("INSERT query");
  207. }
  208. } else {
  209. // compiled statement
  210. if (mysql_stmt_bind_param(stmt, bind)) {
  211. failure("Failed to bind parameters: mysql_stmt_bind_param() returned non-zero");
  212. }
  213. if (mysql_stmt_execute(stmt)) {
  214. failure("Failed to execute statement: mysql_stmt_execute() returned non-zero");
  215. }
  216. }
  217. if (verbose_) {
  218. cout << ".";
  219. }
  220. }
  221. if (compiled_stmt_) {
  222. if (mysql_stmt_close(stmt)) {
  223. failure("Failed to close compiled statement, mysql_stmt_close returned non-zero");
  224. }
  225. }
  226. cout << endl;
  227. }
  228. void MySQL_uBenchmark::searchLease4Test() {
  229. if (!conn_) {
  230. throw "Not connected to MySQL server.";
  231. }
  232. cout << "RETRIEVE: ";
  233. uint32_t addr = 0;
  234. MYSQL_STMT * stmt = NULL;
  235. MYSQL_BIND bind[1]; // just a single element
  236. if (compiled_stmt_) {
  237. stmt = mysql_stmt_init(conn_);
  238. if (!stmt) {
  239. failure("Unable to create compiled statement");
  240. }
  241. const char * statement = "SELECT lease_id,addr,hwaddr,client_id,"
  242. "valid_lft, cltt,pool_id,fixed,hostname,fqdn_fwd,fqdn_rev "
  243. "FROM lease4 where addr=?";
  244. if (mysql_stmt_prepare(stmt, statement, strlen(statement))) {
  245. failure("Failed to prepare statement, mysql_stmt_prepare() returned non-zero");
  246. }
  247. int param_cnt = mysql_stmt_param_count(stmt);
  248. if (param_cnt != 1) {
  249. failure("Parameter count sanity check failed.");
  250. }
  251. memset(bind, 0, sizeof(bind));
  252. // 1st parameter: IPv4 address
  253. bind[0].buffer_type = MYSQL_TYPE_LONG;
  254. bind[0].buffer = (&addr);
  255. bind[0].is_null = 0;
  256. bind[0].length = 0;
  257. }
  258. for (uint32_t i = 0; i < num_; i++) {
  259. addr = BASE_ADDR4 + random() % int(num_ / hitratio_);
  260. if (!compiled_stmt_) {
  261. char query[512];
  262. sprintf(query, "SELECT lease_id,addr,hwaddr,client_id,valid_lft,"
  263. "cltt,pool_id,fixed,hostname,fqdn_fwd,fqdn_rev "
  264. "FROM lease4 where addr=%d", addr);
  265. mysql_real_query(conn_, query, strlen(query));
  266. MYSQL_RES * result = mysql_store_result(conn_);
  267. int num_rows = mysql_num_rows(result);
  268. int num_fields = mysql_num_fields(result);
  269. if ( (num_rows > 1) ) {
  270. stringstream tmp;
  271. tmp << "Search: DB returned " << num_rows << " leases for address "
  272. << hex << addr << dec;
  273. failure(tmp.str().c_str());
  274. }
  275. if (num_rows) {
  276. if (num_fields == 0) {
  277. failure("Query returned empty set");
  278. }
  279. MYSQL_ROW row = mysql_fetch_row(result);
  280. // pretend to do something with it
  281. if (row[0] == NULL) {
  282. failure("SELECT returned NULL data.");
  283. }
  284. mysql_free_result(result);
  285. if (verbose_) {
  286. cout << "."; // hit
  287. }
  288. } else {
  289. if (verbose_) {
  290. cout << "x"; // miss
  291. }
  292. }
  293. } else {
  294. // compiled statement
  295. if (mysql_stmt_bind_param(stmt, bind)) {
  296. failure("Failed to bind parameters: mysql_stmt_bind_param() returned non-zero");
  297. }
  298. if (mysql_stmt_execute(stmt)) {
  299. failure("Failed to execute statement: mysql_stmt_execute() returned non-zero");
  300. }
  301. MYSQL_BIND response[11];
  302. size_t length[11];
  303. my_bool is_null[11];
  304. my_bool error[11];
  305. uint32_t lease_id;
  306. uint32_t lease_addr;
  307. char hwaddr[20];
  308. char client_id[128];
  309. uint32_t valid_lft; // We can use the same value for all leases
  310. MYSQL_TIME cltt;
  311. uint32_t pool_id;
  312. my_bool fixed;
  313. char hostname[255];
  314. my_bool fqdn_fwd;
  315. my_bool fqdn_rev;
  316. for (int j = 0; j < 11; j++) {
  317. response[j].is_null = &is_null[j];
  318. response[j].length = &length[j];
  319. response[j].error = &error[j];
  320. }
  321. // 1th parameter: lease_id
  322. response[0].buffer_type = MYSQL_TYPE_LONG;
  323. response[0].buffer = (&lease_id);
  324. // 2nd parameter: IPv4 address
  325. response[1].buffer_type = MYSQL_TYPE_LONG;
  326. response[1].buffer = (&lease_addr);
  327. // 3rd parameter: Hardware address
  328. response[2].buffer_type = MYSQL_TYPE_STRING;
  329. response[2].buffer = hwaddr;
  330. response[2].buffer_length = sizeof(hwaddr);
  331. // 4th parameter: Client-id
  332. response[3].buffer_type = MYSQL_TYPE_STRING;
  333. response[3].buffer = &client_id;
  334. // 5th parameter: valid-lifetime
  335. response[4].buffer_type = MYSQL_TYPE_LONG;
  336. response[4].buffer = &valid_lft;
  337. // 6th parameter: cltt
  338. response[5].buffer_type = MYSQL_TYPE_TIMESTAMP;
  339. response[5].buffer = &cltt;
  340. // 7th parameter: pool-id
  341. response[6].buffer_type = MYSQL_TYPE_LONG;
  342. response[6].buffer = &pool_id;
  343. // 8th parameter: fixed
  344. response[7].buffer_type = MYSQL_TYPE_TINY;
  345. response[7].buffer = &fixed;
  346. // 9th parameter: hostname
  347. response[8].buffer_type = MYSQL_TYPE_STRING;
  348. response[8].buffer = &hostname;
  349. // 10th parameter: fqdn_fwd
  350. response[9].buffer_type = MYSQL_TYPE_TINY;
  351. response[9].buffer = &fqdn_fwd;
  352. // 11th parameter: fqdn_rev
  353. response[10].buffer_type = MYSQL_TYPE_TINY;
  354. response[10].buffer = &fqdn_rev;
  355. if (mysql_stmt_bind_result(stmt, response))
  356. {
  357. cout << "Error:" << mysql_stmt_error(stmt) << endl;
  358. failure("mysql_stmt_bind_result() failed");
  359. }
  360. int num_rows = 0;
  361. if (!mysql_stmt_fetch(stmt)) {
  362. if (lease_addr != addr) {
  363. failure("Returned data is bogus!");
  364. }
  365. num_rows++;
  366. }
  367. // we could call mysql_stmt_fetch again to check that there are no
  368. // other data for us. But there should be exactly one row of data
  369. // with specified address.
  370. if (num_rows) {
  371. if (verbose_) {
  372. cout << "."; // hit
  373. }
  374. } else {
  375. if (verbose_) {
  376. cout << "X"; // miss
  377. }
  378. }
  379. }
  380. }
  381. if (compiled_stmt_) {
  382. if (mysql_stmt_close(stmt)) {
  383. failure("Failed to close compiled statement, mysql_stmt_close returned non-zero");
  384. }
  385. }
  386. cout << endl;
  387. }
  388. void MySQL_uBenchmark::updateLease4Test() {
  389. if (!conn_) {
  390. throw "Not connected to MySQL server.";
  391. }
  392. cout << "UPDATE: ";
  393. uint32_t valid_lft = 1002; // just some dummy value
  394. char cltt[] = "now()";
  395. size_t cltt_len = strlen(cltt);
  396. uint32_t addr = 0;
  397. MYSQL_STMT * stmt = NULL;
  398. MYSQL_BIND bind[3];
  399. if (compiled_stmt_) {
  400. stmt = mysql_stmt_init(conn_);
  401. if (!stmt) {
  402. failure("Unable to create compiled statement");
  403. }
  404. const char * statement = "UPDATE lease4 SET valid_lft=?, cltt=? WHERE addr=?";
  405. if (mysql_stmt_prepare(stmt, statement, strlen(statement))) {
  406. failure("Failed to prepare statement, mysql_stmt_prepare() returned non-zero");
  407. }
  408. int param_cnt = mysql_stmt_param_count(stmt);
  409. if (param_cnt != 3) {
  410. failure("Parameter count sanity check failed.");
  411. }
  412. memset(bind, 0, sizeof(bind));
  413. // 1st parameter: valid lifetime
  414. bind[0].buffer_type = MYSQL_TYPE_LONG;
  415. bind[0].buffer = &valid_lft;
  416. // 2nd parameter: cltt
  417. bind[1].buffer_type = MYSQL_TYPE_STRING;
  418. bind[1].buffer = &cltt;
  419. bind[1].buffer_length = cltt_len;
  420. bind[2].buffer_type = MYSQL_TYPE_LONG;
  421. bind[2].buffer = &addr;
  422. }
  423. for (uint32_t i = 0; i < num_; i++) {
  424. addr = BASE_ADDR4 + random() % num_;
  425. if (!compiled_stmt_) {
  426. char query[128];
  427. sprintf(query, "UPDATE lease4 SET valid_lft=1002, cltt=now() WHERE addr=%d", addr);
  428. mysql_real_query(conn_, query, strlen(query));
  429. } else {
  430. // compiled statement
  431. if (mysql_stmt_bind_param(stmt, bind)) {
  432. failure("Failed to bind parameters: mysql_stmt_bind_param() returned non-zero");
  433. }
  434. if (mysql_stmt_execute(stmt)) {
  435. failure("Failed to execute statement: mysql_stmt_execute() returned non-zero");
  436. }
  437. }
  438. if (verbose_) {
  439. cout << ".";
  440. }
  441. }
  442. if (compiled_stmt_) {
  443. if (mysql_stmt_close(stmt)) {
  444. failure("Failed to close compiled statement, mysql_stmt_close returned non-zero");
  445. }
  446. }
  447. cout << endl;
  448. }
  449. void MySQL_uBenchmark::deleteLease4Test() {
  450. if (!conn_) {
  451. throw "Not connected to MySQL server.";
  452. }
  453. cout << "DELETE: ";
  454. uint32_t addr = 0;
  455. MYSQL_STMT * stmt = NULL;
  456. MYSQL_BIND bind[1]; // just a single element
  457. if (compiled_stmt_) {
  458. stmt = mysql_stmt_init(conn_);
  459. if (!stmt) {
  460. failure("Unable to create compiled statement, mysql_stmt_init() failed");
  461. }
  462. const char * statement = "DELETE FROM lease4 WHERE addr=?";
  463. if (mysql_stmt_prepare(stmt, statement, strlen(statement) )) {
  464. failure("Failed to prepare statement, mysql_stmt_prepare() returned non-zero");
  465. }
  466. int param_cnt = mysql_stmt_param_count(stmt);
  467. if (param_cnt != 1) {
  468. failure("Parameter count sanity check failed.");
  469. }
  470. memset(bind, 0, sizeof(bind));
  471. // 1st parameter: IPv4 address
  472. bind[0].buffer_type = MYSQL_TYPE_LONG;
  473. bind[0].buffer = (&addr);
  474. bind[0].is_null = 0;
  475. bind[0].length = 0;
  476. }
  477. for (uint32_t i = 0; i < num_; i++) {
  478. addr = BASE_ADDR4 + i;
  479. if (!compiled_stmt_) {
  480. char query[128];
  481. sprintf(query, "DELETE FROM lease4 WHERE addr=%d", addr);
  482. mysql_real_query(conn_, query, strlen(query));
  483. } else {
  484. // compiled statement
  485. if (mysql_stmt_bind_param(stmt, bind)) {
  486. failure("Failed to bind parameters: mysql_stmt_bind_param() returned non-zero");
  487. }
  488. if (mysql_stmt_execute(stmt)) {
  489. failure("Failed to execute statement: mysql_stmt_execute() returned non-zero");
  490. }
  491. }
  492. if (verbose_) {
  493. cout << ".";
  494. }
  495. }
  496. if (compiled_stmt_) {
  497. if (mysql_stmt_close(stmt)) {
  498. failure("Failed to close compiled statement, mysql_stmt_close returned non-zero");
  499. }
  500. }
  501. cout << endl;
  502. }
  503. void MySQL_uBenchmark::printInfo() {
  504. cout << "MySQL client version is " << mysql_get_client_info() << endl;
  505. }
  506. int main(int argc, char * const argv[]) {
  507. const char* hostname ="localhost"; // -m (MySQL server)
  508. const char* user = "root"; // -u
  509. const char* passwd = "secret"; // -p
  510. const char* dbname = "kea"; // -f
  511. uint32_t num = 100; // -n
  512. bool sync = true; // -s
  513. bool verbose = true; // -v
  514. MySQL_uBenchmark bench(hostname, user, passwd, dbname, num, sync, verbose);
  515. bench.parseCmdline(argc, argv);
  516. int result = bench.run();
  517. return (result);
  518. }