sqlite_ubench.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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 <stdio.h>
  15. #include <stdlib.h>
  16. #include <stdint.h>
  17. #include <string.h>
  18. #include <sstream>
  19. #include <iostream>
  20. #include <sqlite3.h>
  21. #include "sqlite_ubench.h"
  22. using namespace std;
  23. SQLite_uBenchmark::SQLite_uBenchmark(const string& filename,
  24. uint32_t num_iterations,
  25. bool sync, bool verbose)
  26. :uBenchmark(num_iterations, filename, sync, verbose),
  27. db_(NULL) {
  28. }
  29. void SQLite_uBenchmark::connect() {
  30. int result = sqlite3_open(dbname_.c_str(), &db_);
  31. if (result != SQLITE_OK) {
  32. failure("Failed to open DB file");
  33. }
  34. result = sqlite3_exec(db_, "DELETE FROM lease4", NULL, NULL, NULL);
  35. if (result != SQLITE_OK) {
  36. failure("Failed to delete old entries");
  37. }
  38. if (sync_) {
  39. sqlite3_exec(db_, "PRAGMA synchronous = ON", NULL, NULL, NULL);
  40. } else {
  41. sqlite3_exec(db_, "PRAGMA synchronous = OFF", NULL, NULL, NULL);
  42. }
  43. // see http://www.sqlite.org/pragma.html#pragma_journal_mode
  44. // for detailed explanation. Available modes: DELETE, TRUNCATE,
  45. // PERSIST, MEMORY, WAL, OFF
  46. sqlite3_exec(db_, "PRAGMA journal_mode = OFF", NULL, NULL, NULL);
  47. }
  48. void SQLite_uBenchmark::disconnect() {
  49. if (db_) {
  50. sqlite3_close(db_);
  51. db_ = NULL;
  52. }
  53. }
  54. void SQLite_uBenchmark::createLease4Test() {
  55. if (!db_) {
  56. throw "SQLite connection is closed.";
  57. }
  58. uint32_t addr = BASE_ADDR4; // Let's start with 1.0.0.0 address
  59. const uint8_t hwaddr_len = 20; // Not a real field
  60. char hwaddr[hwaddr_len];
  61. const uint8_t client_id_len = 128;
  62. char client_id[client_id_len];
  63. uint32_t valid_lft = 1000; // We can use the same value for all leases
  64. uint32_t recycle_time = 0; // Not supported in any foresable future,
  65. // so keep this as 0
  66. char cltt[48]; // Timestamp
  67. uint32_t pool_id = 0; // Let's use pools 0-99
  68. bool fixed = false;
  69. string hostname("foo"); // Will generate it dynamically
  70. bool fqdn_fwd = true; // Let's pretend to do AAAA update
  71. bool fqdn_rev = true; // Let's pretend to do PTR update
  72. printf("CREATE: ");
  73. for (uint8_t i = 0; i < hwaddr_len; i++) {
  74. hwaddr[i] = 65 + i;
  75. }
  76. hwaddr[19] = 0; // workaround
  77. for (uint8_t i = 0; i < client_id_len; i++) {
  78. client_id[i] = 33 + i;
  79. }
  80. client_id[6] = 'X'; // there's apostrophe here. It would confuse
  81. // query formatting, let's get rid of it
  82. client_id[127] = 0; // workaround
  83. sqlite3_stmt *stmt = NULL;
  84. if (compiled_stmt_) {
  85. char query[] = "INSERT INTO lease4(addr,hwaddr,client_id,"
  86. "valid_lft,recycle_time,cltt,pool_id,fixed,hostname,"
  87. "fqdn_fwd,fqdn_rev) VALUES(?001,?002,?003,?004,?005,?006,?007,?008,?009,?010,?011);";
  88. int result = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, NULL);
  89. if (result != SQLITE_OK) {
  90. failure("Failed to compile statement");
  91. }
  92. }
  93. for (uint32_t i = 0; i < num_; i++) {
  94. sprintf(cltt, "2012-07-11 15:43:%02d", i % 60);
  95. addr++;
  96. char* errorMsg = NULL;
  97. if (!compiled_stmt_) {
  98. // the first address is 1.0.0.0.
  99. char query[2000];
  100. /// @todo: Encode HWADDR and CLIENT-ID properly
  101. sprintf(query, "INSERT INTO lease4(addr,hwaddr,client_id,"
  102. "valid_lft,recycle_time,cltt,pool_id,fixed,hostname,"
  103. "fqdn_fwd,fqdn_rev) VALUES(%u,'%s','%s',%d,%d,'%s',%d,'%s','%s','%s','%s');",
  104. addr, hwaddr, client_id, valid_lft, recycle_time,
  105. cltt, pool_id, (fixed?"true":"false"),
  106. hostname.c_str(), (fqdn_fwd?"true":"false"), (fqdn_rev?"true":"false"));
  107. // printf("QUERY=[%s]\n", query);
  108. int result = sqlite3_exec(db_, query, NULL, 0, &errorMsg);
  109. if (result != SQLITE_OK) {
  110. stringstream tmp;
  111. tmp << "INSERT error:" << errorMsg;
  112. failure(tmp.str().c_str());
  113. }
  114. } else {
  115. // compiled statement
  116. int result = sqlite3_bind_int(stmt, 1, addr);
  117. if (result != SQLITE_OK) {
  118. failure("sqlite3_bind_int() for column 1");
  119. }
  120. result = sqlite3_bind_blob(stmt, 2, hwaddr, hwaddr_len, NULL);
  121. if (result != SQLITE_OK) {
  122. failure("sqlite3_bind_blob() for column 2");
  123. }
  124. result = sqlite3_bind_blob(stmt, 3, client_id, client_id_len, NULL);
  125. if (result != SQLITE_OK) {
  126. failure("sqlite3_bind_blob() for column 3");
  127. }
  128. if (sqlite3_bind_int(stmt, 4, valid_lft) != SQLITE_OK) {
  129. failure("sqlite3_bind_int() for column 4");
  130. }
  131. if (sqlite3_bind_int(stmt, 5, recycle_time) != SQLITE_OK) {
  132. failure("sqlite3_bind_int() for column 5");
  133. }
  134. if (sqlite3_bind_text(stmt, 6, cltt, strlen(cltt), NULL) != SQLITE_OK) {
  135. failure("sqlite3_bind_int() for column 6");
  136. }
  137. if (sqlite3_bind_int(stmt, 7, pool_id) != SQLITE_OK) {
  138. failure("sqlite3_bind_int() for column 7");
  139. }
  140. if (sqlite3_bind_int(stmt, 7, pool_id) != SQLITE_OK) {
  141. failure("sqlite3_bind_int() for column 7");
  142. }
  143. if (sqlite3_bind_int(stmt, 8, fixed) != SQLITE_OK) {
  144. failure("sqlite3_bind_int() for column 8");
  145. }
  146. if (sqlite3_bind_text(stmt, 9, hostname.c_str(), hostname.length(), NULL) != SQLITE_OK) {
  147. failure("sqlite3_bind_int() for column 9");
  148. }
  149. if (sqlite3_bind_int(stmt, 10, fqdn_fwd) != SQLITE_OK) {
  150. failure("sqlite3_bind_int() for column 10");
  151. }
  152. if (sqlite3_bind_int(stmt, 11, fqdn_rev) != SQLITE_OK) {
  153. failure("sqlite3_bind_int() for column 11");
  154. }
  155. result = sqlite3_step(stmt);
  156. if (result != SQLITE_DONE) {
  157. failure("Failed to execute INSERT clause");
  158. }
  159. // let's reset the compiled statement, so it can be used in the
  160. // next iteration
  161. result = sqlite3_reset(stmt);
  162. if (result != SQLITE_OK) {
  163. failure("Failed to execute sqlite3_reset()");
  164. }
  165. }
  166. if (verbose_) {
  167. printf(".");
  168. }
  169. }
  170. if (compiled_stmt_) {
  171. int result = sqlite3_finalize(stmt);
  172. if (result != SQLITE_OK) {
  173. failure("sqlite3_finalize() failed");
  174. }
  175. }
  176. printf("\n");
  177. }
  178. static int search_callback(void *counter, int /*argc*/, char** /*argv*/,
  179. char** /*azColName*/){
  180. int* cnt = static_cast<int*>(counter);
  181. (*cnt)++;
  182. #if 0
  183. int i;
  184. for(i=0; i<argc; i++){
  185. printf("%s=%s ", azColName[i], argv[i] ? argv[i] : "NULL");
  186. }
  187. printf("\n");
  188. #endif
  189. return 0;
  190. }
  191. void SQLite_uBenchmark::searchLease4Test() {
  192. if (!db_) {
  193. throw "SQLite connection is closed.";
  194. }
  195. printf("RETRIEVE: ");
  196. sqlite3_stmt *stmt = NULL;
  197. if (compiled_stmt_) {
  198. const char query[] = "SELECT lease_id,addr,hwaddr,client_id,valid_lft,"
  199. "cltt,pool_id,fixed,hostname,fqdn_fwd,fqdn_rev "
  200. "FROM lease4 where addr=?1";
  201. int result = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, NULL);
  202. if (result != SQLITE_OK) {
  203. failure("Failed to compile statement");
  204. }
  205. }
  206. for (uint32_t i = 0; i < num_; i++) {
  207. uint32_t addr = BASE_ADDR4 + random() % int(num_ / hitratio_);
  208. int cnt = 0;
  209. if (!compiled_stmt_) {
  210. char* errorMsg = NULL;
  211. char query[512];
  212. sprintf(query, "SELECT lease_id,addr,hwaddr,client_id,valid_lft,"
  213. "cltt,pool_id,fixed,hostname,fqdn_fwd,fqdn_rev "
  214. "FROM lease4 where addr=%d", addr);
  215. int result = sqlite3_exec(db_, query, search_callback, &cnt, &errorMsg);
  216. if (result != SQLITE_OK) {
  217. stringstream tmp;
  218. tmp << "SELECT failed: " << errorMsg;
  219. failure(tmp.str().c_str());
  220. }
  221. } else {
  222. // compiled statement
  223. int result = sqlite3_bind_int(stmt, 1, addr);
  224. if (result != SQLITE_OK) {
  225. failure("sqlite3_bind_int() for column 1");
  226. }
  227. result = sqlite3_step(stmt);
  228. switch (result) {
  229. case SQLITE_ROW:
  230. {
  231. uint32_t lease_addr = sqlite3_column_int(stmt, 1);
  232. const void * lease_hwaddr = sqlite3_column_blob(stmt, 2);
  233. uint32_t lease_hwaddr_len = sqlite3_column_bytes(stmt, 2);
  234. const void * lease_clientid = sqlite3_column_blob(stmt, 3);
  235. uint32_t lease_clientid_len = sqlite3_column_bytes(stmt, 3);
  236. uint32_t lease_valid_lft = sqlite3_column_int(stmt, 4);
  237. // cltt
  238. const unsigned char *lease_cltt = sqlite3_column_text(stmt, 5);
  239. uint32_t lease_pool_id = sqlite3_column_int(stmt, 6);
  240. uint32_t lease_fixed = sqlite3_column_int(stmt, 7);
  241. const unsigned char *lease_hostname = sqlite3_column_text(stmt, 8);
  242. uint32_t lease_fqdn_fwd = sqlite3_column_int(stmt, 9);
  243. uint32_t lease_fqdn_rev = sqlite3_column_int(stmt, 10);
  244. if (lease_addr || lease_hwaddr || lease_hwaddr_len || lease_clientid ||
  245. lease_clientid_len || lease_valid_lft || lease_cltt || lease_pool_id ||
  246. lease_fixed || lease_hostname || lease_fqdn_fwd || lease_fqdn_rev) {
  247. // we don't need this information, we just want to obtain it to measure
  248. // the overhead. That strange if is only to quell compiler/cppcheck
  249. // warning about unused variables.
  250. cnt = 1;
  251. }
  252. cnt = 1; // there is at least one row
  253. break;
  254. }
  255. case SQLITE_DONE:
  256. cnt = 0; // there are no rows at all (i.e. no such lease)
  257. break;
  258. default:
  259. failure("Failed to execute SELECT clause");
  260. }
  261. // let's reset the compiled statement, so it can be used in the
  262. // next iteration
  263. result = sqlite3_reset(stmt);
  264. if (result != SQLITE_OK) {
  265. failure("Failed to execute sqlite3_reset()");
  266. }
  267. }
  268. if (verbose_) {
  269. printf("%s", (cnt?".":"X"));
  270. }
  271. }
  272. if (compiled_stmt_) {
  273. int result = sqlite3_finalize(stmt);
  274. if (result != SQLITE_OK) {
  275. failure("sqlite3_finalize() failed");
  276. }
  277. }
  278. printf("\n");
  279. }
  280. void SQLite_uBenchmark::updateLease4Test() {
  281. if (!db_) {
  282. throw "SQLite connection is closed.";
  283. }
  284. printf("UPDATE: ");
  285. sqlite3_stmt *stmt = NULL;
  286. if (compiled_stmt_) {
  287. const char query[] = "UPDATE lease4 SET valid_lft=1002, cltt='now' WHERE addr=?1";
  288. int result = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, NULL);
  289. if (result != SQLITE_OK) {
  290. failure("Failed to compile statement");
  291. }
  292. }
  293. for (uint32_t i = 0; i < num_; i++) {
  294. uint32_t addr = BASE_ADDR4 + random() % num_;
  295. if (!compiled_stmt_) {
  296. char* errorMsg = NULL;
  297. char query[512];
  298. sprintf(query, "UPDATE lease4 SET valid_lft=1002, cltt='now' WHERE addr=%d",
  299. addr);
  300. int result = sqlite3_exec(db_, query, NULL /* no callback here*/, 0, &errorMsg);
  301. if (result != SQLITE_OK) {
  302. stringstream tmp;
  303. tmp << "UPDATE error:" << errorMsg;
  304. failure(tmp.str().c_str());
  305. }
  306. } else {
  307. int result = sqlite3_bind_int(stmt, 1, addr);
  308. if (result != SQLITE_OK) {
  309. failure("sqlite3_bind_int() for column 1");
  310. }
  311. result = sqlite3_step(stmt);
  312. if (result != SQLITE_OK && result != SQLITE_DONE) {
  313. failure("Failed to execute sqlite3_step() for UPDATE");
  314. }
  315. // let's reset the compiled statement, so it can be used in the
  316. // next iteration
  317. result = sqlite3_reset(stmt);
  318. if (result != SQLITE_OK) {
  319. failure("Failed to execute sqlite3_reset()");
  320. }
  321. }
  322. if (verbose_) {
  323. printf(".");
  324. }
  325. }
  326. if (compiled_stmt_) {
  327. int result = sqlite3_finalize(stmt);
  328. if (result != SQLITE_OK) {
  329. failure("sqlite3_finalize() failed");
  330. }
  331. }
  332. printf("\n");
  333. }
  334. void SQLite_uBenchmark::deleteLease4Test() {
  335. if (!db_) {
  336. throw "SQLite connection is closed.";
  337. }
  338. printf("DELETE: ");
  339. sqlite3_stmt *stmt = NULL;
  340. if (compiled_stmt_) {
  341. const char query[] = "DELETE FROM lease4 WHERE addr=?1";
  342. int result = sqlite3_prepare_v2(db_, query, strlen(query), &stmt, NULL);
  343. if (result != SQLITE_OK) {
  344. failure("Failed to compile statement");
  345. }
  346. }
  347. for (uint32_t i = 0; i < num_; i++) {
  348. uint32_t addr = BASE_ADDR4 + i;
  349. if (!compiled_stmt_) {
  350. char* errorMsg = NULL;
  351. char query[2000];
  352. sprintf(query, "DELETE FROM lease4 WHERE addr=%d", addr);
  353. int result = sqlite3_exec(db_, query, NULL /* no callback here*/, 0, &errorMsg);
  354. if (result != SQLITE_OK) {
  355. stringstream tmp;
  356. tmp << "DELETE error:" << errorMsg;
  357. failure(tmp.str().c_str());
  358. }
  359. } else {
  360. // compiled statement
  361. int result = sqlite3_bind_int(stmt, 1, addr);
  362. if (result != SQLITE_OK) {
  363. failure("sqlite3_bind_int() for column 1");
  364. }
  365. result = sqlite3_step(stmt);
  366. if (result != SQLITE_OK && result != SQLITE_DONE) {
  367. failure("Failed to execute sqlite3_step() for UPDATE");
  368. }
  369. // let's reset the compiled statement, so it can be used in the
  370. // next iteration
  371. result = sqlite3_reset(stmt);
  372. if (result != SQLITE_OK) {
  373. failure("Failed to execute sqlite3_reset()");
  374. }
  375. }
  376. if (verbose_) {
  377. printf(".");
  378. }
  379. }
  380. if (compiled_stmt_) {
  381. int result = sqlite3_finalize(stmt);
  382. if (result != SQLITE_OK) {
  383. failure("sqlite3_finalize() failed");
  384. }
  385. }
  386. printf("\n");
  387. }
  388. void SQLite_uBenchmark::printInfo() {
  389. cout << "SQLite version is " << sqlite3_libversion()
  390. << "sourceid version is " << sqlite3_sourceid() << endl;
  391. }
  392. int main(int argc, char* const argv[]) {
  393. const char* filename = "sqlite.db";
  394. uint32_t num = 100;
  395. bool sync = true;
  396. bool verbose = true;
  397. SQLite_uBenchmark bench(filename, num, sync, verbose);
  398. bench.parseCmdline(argc, argv);
  399. int result = bench.run();
  400. return (result);
  401. }