OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ** A program for performance testing. |
| 3 ** |
| 4 ** The available command-line options are described below: |
| 5 */ |
| 6 static const char zHelp[] = |
| 7 "Usage: %s [--options] DATABASE\n" |
| 8 "Options:\n" |
| 9 " --autovacuum Enable AUTOVACUUM mode\n" |
| 10 " --cachesize N Set the cache size to N\n" |
| 11 " --exclusive Enable locking_mode=EXCLUSIVE\n" |
| 12 " --explain Like --sqlonly but with added EXPLAIN keywords\n" |
| 13 " --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n" |
| 14 " --incrvacuum Enable incremenatal vacuum mode\n" |
| 15 " --journalmode M Set the journal_mode to MODE\n" |
| 16 " --key KEY Set the encryption key to KEY\n" |
| 17 " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" |
| 18 " --nosync Set PRAGMA synchronous=OFF\n" |
| 19 " --notnull Add NOT NULL constraints to table columns\n" |
| 20 " --pagesize N Set the page size to N\n" |
| 21 " --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n" |
| 22 " --primarykey Use PRIMARY KEY instead of UNIQUE where appropriate\n" |
| 23 " --reprepare Reprepare each statement upon every invocation\n" |
| 24 " --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n
" |
| 25 " --sqlonly No-op. Only show the SQL that would have been run.\n" |
| 26 " --size N Relative test size. Default=100\n" |
| 27 " --stats Show statistics at the end\n" |
| 28 " --testset T Run test-set T\n" |
| 29 " --trace Turn on SQL tracing\n" |
| 30 " --threads N Use up to N threads for sorting\n" |
| 31 " --utf16be Set text encoding to UTF-16BE\n" |
| 32 " --utf16le Set text encoding to UTF-16LE\n" |
| 33 " --verify Run additional verification steps.\n" |
| 34 " --without-rowid Use WITHOUT ROWID where appropriate\n" |
| 35 ; |
| 36 |
| 37 |
| 38 #include "sqlite3.h" |
| 39 #include <assert.h> |
| 40 #include <stdio.h> |
| 41 #include <stdlib.h> |
| 42 #include <stdarg.h> |
| 43 #include <string.h> |
| 44 #include <ctype.h> |
| 45 |
| 46 /* All global state is held in this structure */ |
| 47 static struct Global { |
| 48 sqlite3 *db; /* The open database connection */ |
| 49 sqlite3_stmt *pStmt; /* Current SQL statement */ |
| 50 sqlite3_int64 iStart; /* Start-time for the current test */ |
| 51 sqlite3_int64 iTotal; /* Total time */ |
| 52 int bWithoutRowid; /* True for --without-rowid */ |
| 53 int bReprepare; /* True to reprepare the SQL on each rerun */ |
| 54 int bSqlOnly; /* True to print the SQL once only */ |
| 55 int bExplain; /* Print SQL with EXPLAIN prefix */ |
| 56 int bVerify; /* Try to verify that results are correct */ |
| 57 int szTest; /* Scale factor for test iterations */ |
| 58 const char *zWR; /* Might be WITHOUT ROWID */ |
| 59 const char *zNN; /* Might be NOT NULL */ |
| 60 const char *zPK; /* Might be UNIQUE or PRIMARY KEY */ |
| 61 unsigned int x, y; /* Pseudo-random number generator state */ |
| 62 int nResult; /* Size of the current result */ |
| 63 char zResult[3000]; /* Text of the current result */ |
| 64 } g; |
| 65 |
| 66 |
| 67 /* Print an error message and exit */ |
| 68 static void fatal_error(const char *zMsg, ...){ |
| 69 va_list ap; |
| 70 va_start(ap, zMsg); |
| 71 vfprintf(stderr, zMsg, ap); |
| 72 va_end(ap); |
| 73 exit(1); |
| 74 } |
| 75 |
| 76 /* |
| 77 ** Return the value of a hexadecimal digit. Return -1 if the input |
| 78 ** is not a hex digit. |
| 79 */ |
| 80 static int hexDigitValue(char c){ |
| 81 if( c>='0' && c<='9' ) return c - '0'; |
| 82 if( c>='a' && c<='f' ) return c - 'a' + 10; |
| 83 if( c>='A' && c<='F' ) return c - 'A' + 10; |
| 84 return -1; |
| 85 } |
| 86 |
| 87 /* Provide an alternative to sqlite3_stricmp() in older versions of |
| 88 ** SQLite */ |
| 89 #if SQLITE_VERSION_NUMBER<3007011 |
| 90 # define sqlite3_stricmp strcmp |
| 91 #endif |
| 92 |
| 93 /* |
| 94 ** Interpret zArg as an integer value, possibly with suffixes. |
| 95 */ |
| 96 static int integerValue(const char *zArg){ |
| 97 sqlite3_int64 v = 0; |
| 98 static const struct { char *zSuffix; int iMult; } aMult[] = { |
| 99 { "KiB", 1024 }, |
| 100 { "MiB", 1024*1024 }, |
| 101 { "GiB", 1024*1024*1024 }, |
| 102 { "KB", 1000 }, |
| 103 { "MB", 1000000 }, |
| 104 { "GB", 1000000000 }, |
| 105 { "K", 1000 }, |
| 106 { "M", 1000000 }, |
| 107 { "G", 1000000000 }, |
| 108 }; |
| 109 int i; |
| 110 int isNeg = 0; |
| 111 if( zArg[0]=='-' ){ |
| 112 isNeg = 1; |
| 113 zArg++; |
| 114 }else if( zArg[0]=='+' ){ |
| 115 zArg++; |
| 116 } |
| 117 if( zArg[0]=='0' && zArg[1]=='x' ){ |
| 118 int x; |
| 119 zArg += 2; |
| 120 while( (x = hexDigitValue(zArg[0]))>=0 ){ |
| 121 v = (v<<4) + x; |
| 122 zArg++; |
| 123 } |
| 124 }else{ |
| 125 while( isdigit(zArg[0]) ){ |
| 126 v = v*10 + zArg[0] - '0'; |
| 127 zArg++; |
| 128 } |
| 129 } |
| 130 for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){ |
| 131 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ |
| 132 v *= aMult[i].iMult; |
| 133 break; |
| 134 } |
| 135 } |
| 136 if( v>0x7fffffff ) fatal_error("parameter too large - max 2147483648"); |
| 137 return (int)(isNeg? -v : v); |
| 138 } |
| 139 |
| 140 /* Return the current wall-clock time, in milliseconds */ |
| 141 sqlite3_int64 speedtest1_timestamp(void){ |
| 142 static sqlite3_vfs *clockVfs = 0; |
| 143 sqlite3_int64 t; |
| 144 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); |
| 145 #if SQLITE_VERSION_NUMBER>=3007000 |
| 146 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ |
| 147 clockVfs->xCurrentTimeInt64(clockVfs, &t); |
| 148 }else |
| 149 #endif |
| 150 { |
| 151 double r; |
| 152 clockVfs->xCurrentTime(clockVfs, &r); |
| 153 t = (sqlite3_int64)(r*86400000.0); |
| 154 } |
| 155 return t; |
| 156 } |
| 157 |
| 158 /* Return a pseudo-random unsigned integer */ |
| 159 unsigned int speedtest1_random(void){ |
| 160 g.x = (g.x>>1) ^ ((1+~(g.x&1)) & 0xd0000001); |
| 161 g.y = g.y*1103515245 + 12345; |
| 162 return g.x ^ g.y; |
| 163 } |
| 164 |
| 165 /* Map the value in within the range of 1...limit into another |
| 166 ** number in a way that is chatic and invertable. |
| 167 */ |
| 168 unsigned swizzle(unsigned in, unsigned limit){ |
| 169 unsigned out = 0; |
| 170 while( limit ){ |
| 171 out = (out<<1) | (in&1); |
| 172 in >>= 1; |
| 173 limit >>= 1; |
| 174 } |
| 175 return out; |
| 176 } |
| 177 |
| 178 /* Round up a number so that it is a power of two minus one |
| 179 */ |
| 180 unsigned roundup_allones(unsigned limit){ |
| 181 unsigned m = 1; |
| 182 while( m<limit ) m = (m<<1)+1; |
| 183 return m; |
| 184 } |
| 185 |
| 186 /* The speedtest1_numbername procedure below converts its argment (an integer) |
| 187 ** into a string which is the English-language name for that number. |
| 188 ** The returned string should be freed with sqlite3_free(). |
| 189 ** |
| 190 ** Example: |
| 191 ** |
| 192 ** speedtest1_numbername(123) -> "one hundred twenty three" |
| 193 */ |
| 194 int speedtest1_numbername(unsigned int n, char *zOut, int nOut){ |
| 195 static const char *ones[] = { "zero", "one", "two", "three", "four", "five", |
| 196 "six", "seven", "eight", "nine", "ten", "eleven", "twelve", |
| 197 "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", |
| 198 "eighteen", "nineteen" }; |
| 199 static const char *tens[] = { "", "ten", "twenty", "thirty", "forty", |
| 200 "fifty", "sixty", "seventy", "eighty", "ninety" }; |
| 201 int i = 0; |
| 202 |
| 203 if( n>=1000000000 ){ |
| 204 i += speedtest1_numbername(n/1000000000, zOut+i, nOut-i); |
| 205 sqlite3_snprintf(nOut-i, zOut+i, " billion"); |
| 206 i += (int)strlen(zOut+i); |
| 207 n = n % 1000000000; |
| 208 } |
| 209 if( n>=1000000 ){ |
| 210 if( i && i<nOut-1 ) zOut[i++] = ' '; |
| 211 i += speedtest1_numbername(n/1000000, zOut+i, nOut-i); |
| 212 sqlite3_snprintf(nOut-i, zOut+i, " million"); |
| 213 i += (int)strlen(zOut+i); |
| 214 n = n % 1000000; |
| 215 } |
| 216 if( n>=1000 ){ |
| 217 if( i && i<nOut-1 ) zOut[i++] = ' '; |
| 218 i += speedtest1_numbername(n/1000, zOut+i, nOut-i); |
| 219 sqlite3_snprintf(nOut-i, zOut+i, " thousand"); |
| 220 i += (int)strlen(zOut+i); |
| 221 n = n % 1000; |
| 222 } |
| 223 if( n>=100 ){ |
| 224 if( i && i<nOut-1 ) zOut[i++] = ' '; |
| 225 sqlite3_snprintf(nOut-i, zOut+i, "%s hundred", ones[n/100]); |
| 226 i += (int)strlen(zOut+i); |
| 227 n = n % 100; |
| 228 } |
| 229 if( n>=20 ){ |
| 230 if( i && i<nOut-1 ) zOut[i++] = ' '; |
| 231 sqlite3_snprintf(nOut-i, zOut+i, "%s", tens[n/10]); |
| 232 i += (int)strlen(zOut+i); |
| 233 n = n % 10; |
| 234 } |
| 235 if( n>0 ){ |
| 236 if( i && i<nOut-1 ) zOut[i++] = ' '; |
| 237 sqlite3_snprintf(nOut-i, zOut+i, "%s", ones[n]); |
| 238 i += (int)strlen(zOut+i); |
| 239 } |
| 240 if( i==0 ){ |
| 241 sqlite3_snprintf(nOut-i, zOut+i, "zero"); |
| 242 i += (int)strlen(zOut+i); |
| 243 } |
| 244 return i; |
| 245 } |
| 246 |
| 247 |
| 248 /* Start a new test case */ |
| 249 #define NAMEWIDTH 60 |
| 250 static const char zDots[] = |
| 251 "......................................................................."; |
| 252 void speedtest1_begin_test(int iTestNum, const char *zTestName, ...){ |
| 253 int n = (int)strlen(zTestName); |
| 254 char *zName; |
| 255 va_list ap; |
| 256 va_start(ap, zTestName); |
| 257 zName = sqlite3_vmprintf(zTestName, ap); |
| 258 va_end(ap); |
| 259 n = (int)strlen(zName); |
| 260 if( n>NAMEWIDTH ){ |
| 261 zName[NAMEWIDTH] = 0; |
| 262 n = NAMEWIDTH; |
| 263 } |
| 264 if( g.bSqlOnly ){ |
| 265 printf("/* %4d - %s%.*s */\n", iTestNum, zName, NAMEWIDTH-n, zDots); |
| 266 }else{ |
| 267 printf("%4d - %s%.*s ", iTestNum, zName, NAMEWIDTH-n, zDots); |
| 268 fflush(stdout); |
| 269 } |
| 270 sqlite3_free(zName); |
| 271 g.nResult = 0; |
| 272 g.iStart = speedtest1_timestamp(); |
| 273 g.x = 0xad131d0b; |
| 274 g.y = 0x44f9eac8; |
| 275 } |
| 276 |
| 277 /* Complete a test case */ |
| 278 void speedtest1_end_test(void){ |
| 279 sqlite3_int64 iElapseTime = speedtest1_timestamp() - g.iStart; |
| 280 if( !g.bSqlOnly ){ |
| 281 g.iTotal += iElapseTime; |
| 282 printf("%4d.%03ds\n", (int)(iElapseTime/1000), (int)(iElapseTime%1000)); |
| 283 } |
| 284 if( g.pStmt ){ |
| 285 sqlite3_finalize(g.pStmt); |
| 286 g.pStmt = 0; |
| 287 } |
| 288 } |
| 289 |
| 290 /* Report end of testing */ |
| 291 void speedtest1_final(void){ |
| 292 if( !g.bSqlOnly ){ |
| 293 printf(" TOTAL%.*s %4d.%03ds\n", NAMEWIDTH-5, zDots, |
| 294 (int)(g.iTotal/1000), (int)(g.iTotal%1000)); |
| 295 } |
| 296 } |
| 297 |
| 298 /* Print an SQL statement to standard output */ |
| 299 static void printSql(const char *zSql){ |
| 300 int n = (int)strlen(zSql); |
| 301 while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; } |
| 302 if( g.bExplain ) printf("EXPLAIN "); |
| 303 printf("%.*s;\n", n, zSql); |
| 304 if( g.bExplain |
| 305 #if SQLITE_VERSION_NUMBER>=3007010 |
| 306 && ( sqlite3_strglob("CREATE *", zSql)==0 |
| 307 || sqlite3_strglob("DROP *", zSql)==0 |
| 308 || sqlite3_strglob("ALTER *", zSql)==0 |
| 309 ) |
| 310 #endif |
| 311 ){ |
| 312 printf("%.*s;\n", n, zSql); |
| 313 } |
| 314 } |
| 315 |
| 316 /* Run SQL */ |
| 317 void speedtest1_exec(const char *zFormat, ...){ |
| 318 va_list ap; |
| 319 char *zSql; |
| 320 va_start(ap, zFormat); |
| 321 zSql = sqlite3_vmprintf(zFormat, ap); |
| 322 va_end(ap); |
| 323 if( g.bSqlOnly ){ |
| 324 printSql(zSql); |
| 325 }else{ |
| 326 char *zErrMsg = 0; |
| 327 int rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); |
| 328 if( zErrMsg ) fatal_error("SQL error: %s\n%s\n", zErrMsg, zSql); |
| 329 if( rc!=SQLITE_OK ) fatal_error("exec error: %s\n", sqlite3_errmsg(g.db)); |
| 330 } |
| 331 sqlite3_free(zSql); |
| 332 } |
| 333 |
| 334 /* Prepare an SQL statement */ |
| 335 void speedtest1_prepare(const char *zFormat, ...){ |
| 336 va_list ap; |
| 337 char *zSql; |
| 338 va_start(ap, zFormat); |
| 339 zSql = sqlite3_vmprintf(zFormat, ap); |
| 340 va_end(ap); |
| 341 if( g.bSqlOnly ){ |
| 342 printSql(zSql); |
| 343 }else{ |
| 344 int rc; |
| 345 if( g.pStmt ) sqlite3_finalize(g.pStmt); |
| 346 rc = sqlite3_prepare_v2(g.db, zSql, -1, &g.pStmt, 0); |
| 347 if( rc ){ |
| 348 fatal_error("SQL error: %s\n", sqlite3_errmsg(g.db)); |
| 349 } |
| 350 } |
| 351 sqlite3_free(zSql); |
| 352 } |
| 353 |
| 354 /* Run an SQL statement previously prepared */ |
| 355 void speedtest1_run(void){ |
| 356 int i, n, len; |
| 357 if( g.bSqlOnly ) return; |
| 358 assert( g.pStmt ); |
| 359 g.nResult = 0; |
| 360 while( sqlite3_step(g.pStmt)==SQLITE_ROW ){ |
| 361 n = sqlite3_column_count(g.pStmt); |
| 362 for(i=0; i<n; i++){ |
| 363 const char *z = (const char*)sqlite3_column_text(g.pStmt, i); |
| 364 if( z==0 ) z = "nil"; |
| 365 len = (int)strlen(z); |
| 366 if( g.nResult+len<sizeof(g.zResult)-2 ){ |
| 367 if( g.nResult>0 ) g.zResult[g.nResult++] = ' '; |
| 368 memcpy(g.zResult + g.nResult, z, len+1); |
| 369 g.nResult += len; |
| 370 } |
| 371 } |
| 372 } |
| 373 if( g.bReprepare ){ |
| 374 sqlite3_stmt *pNew; |
| 375 sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0); |
| 376 sqlite3_finalize(g.pStmt); |
| 377 g.pStmt = pNew; |
| 378 }else{ |
| 379 sqlite3_reset(g.pStmt); |
| 380 } |
| 381 } |
| 382 |
| 383 /* The sqlite3_trace() callback function */ |
| 384 static void traceCallback(void *NotUsed, const char *zSql){ |
| 385 int n = (int)strlen(zSql); |
| 386 while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ) n--; |
| 387 fprintf(stderr,"%.*s;\n", n, zSql); |
| 388 } |
| 389 |
| 390 /* Substitute random() function that gives the same random |
| 391 ** sequence on each run, for repeatability. */ |
| 392 static void randomFunc( |
| 393 sqlite3_context *context, |
| 394 int NotUsed, |
| 395 sqlite3_value **NotUsed2 |
| 396 ){ |
| 397 sqlite3_result_int64(context, (sqlite3_int64)speedtest1_random()); |
| 398 } |
| 399 |
| 400 /* Estimate the square root of an integer */ |
| 401 static int est_square_root(int x){ |
| 402 int y0 = x/2; |
| 403 int y1; |
| 404 int n; |
| 405 for(n=0; y0>0 && n<10; n++){ |
| 406 y1 = (y0 + x/y0)/2; |
| 407 if( y1==y0 ) break; |
| 408 y0 = y1; |
| 409 } |
| 410 return y0; |
| 411 } |
| 412 |
| 413 /* |
| 414 ** The main and default testset |
| 415 */ |
| 416 void testset_main(void){ |
| 417 int i; /* Loop counter */ |
| 418 int n; /* iteration count */ |
| 419 int sz; /* Size of the tables */ |
| 420 int maxb; /* Maximum swizzled value */ |
| 421 unsigned x1, x2; /* Parameters */ |
| 422 int len; /* Length of the zNum[] string */ |
| 423 char zNum[2000]; /* A number name */ |
| 424 |
| 425 sz = n = g.szTest*500; |
| 426 maxb = roundup_allones(sz); |
| 427 speedtest1_begin_test(100, "%d INSERTs into table with no index", n); |
| 428 speedtest1_exec("BEGIN"); |
| 429 speedtest1_exec("CREATE TABLE t1(a INTEGER %s, b INTEGER %s, c TEXT %s);", |
| 430 g.zNN, g.zNN, g.zNN); |
| 431 speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2,?3); -- %d times", n); |
| 432 for(i=1; i<=n; i++){ |
| 433 x1 = swizzle(i,maxb); |
| 434 speedtest1_numbername(x1, zNum, sizeof(zNum)); |
| 435 sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1); |
| 436 sqlite3_bind_int(g.pStmt, 2, i); |
| 437 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC); |
| 438 speedtest1_run(); |
| 439 } |
| 440 speedtest1_exec("COMMIT"); |
| 441 speedtest1_end_test(); |
| 442 |
| 443 |
| 444 n = sz; |
| 445 speedtest1_begin_test(110, "%d ordered INSERTS with one index/PK", n); |
| 446 speedtest1_exec("BEGIN"); |
| 447 speedtest1_exec("CREATE TABLE t2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s"
, |
| 448 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR); |
| 449 speedtest1_prepare("INSERT INTO t2 VALUES(?1,?2,?3); -- %d times", n); |
| 450 for(i=1; i<=n; i++){ |
| 451 x1 = swizzle(i,maxb); |
| 452 speedtest1_numbername(x1, zNum, sizeof(zNum)); |
| 453 sqlite3_bind_int(g.pStmt, 1, i); |
| 454 sqlite3_bind_int64(g.pStmt, 2, (sqlite3_int64)x1); |
| 455 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC); |
| 456 speedtest1_run(); |
| 457 } |
| 458 speedtest1_exec("COMMIT"); |
| 459 speedtest1_end_test(); |
| 460 |
| 461 |
| 462 n = sz; |
| 463 speedtest1_begin_test(120, "%d unordered INSERTS with one index/PK", n); |
| 464 speedtest1_exec("BEGIN"); |
| 465 speedtest1_exec("CREATE TABLE t3(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s"
, |
| 466 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR); |
| 467 speedtest1_prepare("INSERT INTO t3 VALUES(?1,?2,?3); -- %d times", n); |
| 468 for(i=1; i<=n; i++){ |
| 469 x1 = swizzle(i,maxb); |
| 470 speedtest1_numbername(x1, zNum, sizeof(zNum)); |
| 471 sqlite3_bind_int(g.pStmt, 2, i); |
| 472 sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1); |
| 473 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC); |
| 474 speedtest1_run(); |
| 475 } |
| 476 speedtest1_exec("COMMIT"); |
| 477 speedtest1_end_test(); |
| 478 |
| 479 |
| 480 n = 25; |
| 481 speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n); |
| 482 speedtest1_exec("BEGIN"); |
| 483 speedtest1_prepare( |
| 484 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n" |
| 485 " WHERE b BETWEEN ?1 AND ?2; -- %d times", n |
| 486 ); |
| 487 for(i=1; i<=n; i++){ |
| 488 x1 = speedtest1_random()%maxb; |
| 489 x2 = speedtest1_random()%10 + sz/5000 + x1; |
| 490 sqlite3_bind_int(g.pStmt, 1, x1); |
| 491 sqlite3_bind_int(g.pStmt, 2, x2); |
| 492 speedtest1_run(); |
| 493 } |
| 494 speedtest1_exec("COMMIT"); |
| 495 speedtest1_end_test(); |
| 496 |
| 497 |
| 498 n = 10; |
| 499 speedtest1_begin_test(140, "%d SELECTS, LIKE, unindexed", n); |
| 500 speedtest1_exec("BEGIN"); |
| 501 speedtest1_prepare( |
| 502 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n" |
| 503 " WHERE c LIKE ?1; -- %d times", n |
| 504 ); |
| 505 for(i=1; i<=n; i++){ |
| 506 x1 = speedtest1_random()%maxb; |
| 507 zNum[0] = '%'; |
| 508 len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); |
| 509 zNum[len] = '%'; |
| 510 zNum[len+1] = 0; |
| 511 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); |
| 512 speedtest1_run(); |
| 513 } |
| 514 speedtest1_exec("COMMIT"); |
| 515 speedtest1_end_test(); |
| 516 |
| 517 |
| 518 n = 10; |
| 519 speedtest1_begin_test(142, "%d SELECTS w/ORDER BY, unindexed", n); |
| 520 speedtest1_exec("BEGIN"); |
| 521 speedtest1_prepare( |
| 522 "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n" |
| 523 " ORDER BY a; -- %d times", n |
| 524 ); |
| 525 for(i=1; i<=n; i++){ |
| 526 x1 = speedtest1_random()%maxb; |
| 527 zNum[0] = '%'; |
| 528 len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); |
| 529 zNum[len] = '%'; |
| 530 zNum[len+1] = 0; |
| 531 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); |
| 532 speedtest1_run(); |
| 533 } |
| 534 speedtest1_exec("COMMIT"); |
| 535 speedtest1_end_test(); |
| 536 |
| 537 n = 10; //g.szTest/5; |
| 538 speedtest1_begin_test(145, "%d SELECTS w/ORDER BY and LIMIT, unindexed", n); |
| 539 speedtest1_exec("BEGIN"); |
| 540 speedtest1_prepare( |
| 541 "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n" |
| 542 " ORDER BY a LIMIT 10; -- %d times", n |
| 543 ); |
| 544 for(i=1; i<=n; i++){ |
| 545 x1 = speedtest1_random()%maxb; |
| 546 zNum[0] = '%'; |
| 547 len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); |
| 548 zNum[len] = '%'; |
| 549 zNum[len+1] = 0; |
| 550 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); |
| 551 speedtest1_run(); |
| 552 } |
| 553 speedtest1_exec("COMMIT"); |
| 554 speedtest1_end_test(); |
| 555 |
| 556 |
| 557 speedtest1_begin_test(150, "CREATE INDEX five times"); |
| 558 speedtest1_exec("BEGIN;"); |
| 559 speedtest1_exec("CREATE UNIQUE INDEX t1b ON t1(b);"); |
| 560 speedtest1_exec("CREATE INDEX t1c ON t1(c);"); |
| 561 speedtest1_exec("CREATE UNIQUE INDEX t2b ON t2(b);"); |
| 562 speedtest1_exec("CREATE INDEX t2c ON t2(c DESC);"); |
| 563 speedtest1_exec("CREATE INDEX t3bc ON t3(b,c);"); |
| 564 speedtest1_exec("COMMIT;"); |
| 565 speedtest1_end_test(); |
| 566 |
| 567 |
| 568 n = sz/5; |
| 569 speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n); |
| 570 speedtest1_exec("BEGIN"); |
| 571 speedtest1_prepare( |
| 572 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n" |
| 573 " WHERE b BETWEEN ?1 AND ?2; -- %d times", n |
| 574 ); |
| 575 for(i=1; i<=n; i++){ |
| 576 x1 = speedtest1_random()%maxb; |
| 577 x2 = speedtest1_random()%10 + sz/5000 + x1; |
| 578 sqlite3_bind_int(g.pStmt, 1, x1); |
| 579 sqlite3_bind_int(g.pStmt, 2, x2); |
| 580 speedtest1_run(); |
| 581 } |
| 582 speedtest1_exec("COMMIT"); |
| 583 speedtest1_end_test(); |
| 584 |
| 585 |
| 586 n = sz/5; |
| 587 speedtest1_begin_test(161, "%d SELECTS, numeric BETWEEN, PK", n); |
| 588 speedtest1_exec("BEGIN"); |
| 589 speedtest1_prepare( |
| 590 "SELECT count(*), avg(b), sum(length(c)) FROM t2\n" |
| 591 " WHERE a BETWEEN ?1 AND ?2; -- %d times", n |
| 592 ); |
| 593 for(i=1; i<=n; i++){ |
| 594 x1 = speedtest1_random()%maxb; |
| 595 x2 = speedtest1_random()%10 + sz/5000 + x1; |
| 596 sqlite3_bind_int(g.pStmt, 1, x1); |
| 597 sqlite3_bind_int(g.pStmt, 2, x2); |
| 598 speedtest1_run(); |
| 599 } |
| 600 speedtest1_exec("COMMIT"); |
| 601 speedtest1_end_test(); |
| 602 |
| 603 |
| 604 n = sz/5; |
| 605 speedtest1_begin_test(170, "%d SELECTS, text BETWEEN, indexed", n); |
| 606 speedtest1_exec("BEGIN"); |
| 607 speedtest1_prepare( |
| 608 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n" |
| 609 " WHERE c BETWEEN ?1 AND (?1||'~'); -- %d times", n |
| 610 ); |
| 611 for(i=1; i<=n; i++){ |
| 612 x1 = swizzle(i, maxb); |
| 613 len = speedtest1_numbername(x1, zNum, sizeof(zNum)-1); |
| 614 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); |
| 615 speedtest1_run(); |
| 616 } |
| 617 speedtest1_exec("COMMIT"); |
| 618 speedtest1_end_test(); |
| 619 |
| 620 n = sz; |
| 621 speedtest1_begin_test(180, "%d INSERTS with three indexes", n); |
| 622 speedtest1_exec("BEGIN"); |
| 623 speedtest1_exec( |
| 624 "CREATE TABLE t4(\n" |
| 625 " a INTEGER %s %s,\n" |
| 626 " b INTEGER %s,\n" |
| 627 " c TEXT %s\n" |
| 628 ") %s", |
| 629 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR); |
| 630 speedtest1_exec("CREATE INDEX t4b ON t4(b)"); |
| 631 speedtest1_exec("CREATE INDEX t4c ON t4(c)"); |
| 632 speedtest1_exec("INSERT INTO t4 SELECT * FROM t1"); |
| 633 speedtest1_exec("COMMIT"); |
| 634 speedtest1_end_test(); |
| 635 |
| 636 n = sz; |
| 637 speedtest1_begin_test(190, "DELETE and REFILL one table", n); |
| 638 speedtest1_exec("DELETE FROM t2;"); |
| 639 speedtest1_exec("INSERT INTO t2 SELECT * FROM t1;"); |
| 640 speedtest1_end_test(); |
| 641 |
| 642 |
| 643 speedtest1_begin_test(200, "VACUUM"); |
| 644 speedtest1_exec("VACUUM"); |
| 645 speedtest1_end_test(); |
| 646 |
| 647 |
| 648 speedtest1_begin_test(210, "ALTER TABLE ADD COLUMN, and query"); |
| 649 speedtest1_exec("ALTER TABLE t2 ADD COLUMN d DEFAULT 123"); |
| 650 speedtest1_exec("SELECT sum(d) FROM t2"); |
| 651 speedtest1_end_test(); |
| 652 |
| 653 |
| 654 n = sz/5; |
| 655 speedtest1_begin_test(230, "%d UPDATES, numeric BETWEEN, indexed", n); |
| 656 speedtest1_exec("BEGIN"); |
| 657 speedtest1_prepare( |
| 658 "UPDATE t2 SET d=b*2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n |
| 659 ); |
| 660 for(i=1; i<=n; i++){ |
| 661 x1 = speedtest1_random()%maxb; |
| 662 x2 = speedtest1_random()%10 + sz/5000 + x1; |
| 663 sqlite3_bind_int(g.pStmt, 1, x1); |
| 664 sqlite3_bind_int(g.pStmt, 2, x2); |
| 665 speedtest1_run(); |
| 666 } |
| 667 speedtest1_exec("COMMIT"); |
| 668 speedtest1_end_test(); |
| 669 |
| 670 |
| 671 n = sz; |
| 672 speedtest1_begin_test(240, "%d UPDATES of individual rows", n); |
| 673 speedtest1_exec("BEGIN"); |
| 674 speedtest1_prepare( |
| 675 "UPDATE t2 SET d=b*3 WHERE a=?1; -- %d times", n |
| 676 ); |
| 677 for(i=1; i<=n; i++){ |
| 678 x1 = speedtest1_random()%sz + 1; |
| 679 sqlite3_bind_int(g.pStmt, 1, x1); |
| 680 speedtest1_run(); |
| 681 } |
| 682 speedtest1_exec("COMMIT"); |
| 683 speedtest1_end_test(); |
| 684 |
| 685 speedtest1_begin_test(250, "One big UPDATE of the whole %d-row table", sz); |
| 686 speedtest1_exec("UPDATE t2 SET d=b*4"); |
| 687 speedtest1_end_test(); |
| 688 |
| 689 |
| 690 speedtest1_begin_test(260, "Query added column after filling"); |
| 691 speedtest1_exec("SELECT sum(d) FROM t2"); |
| 692 speedtest1_end_test(); |
| 693 |
| 694 |
| 695 |
| 696 n = sz/5; |
| 697 speedtest1_begin_test(270, "%d DELETEs, numeric BETWEEN, indexed", n); |
| 698 speedtest1_exec("BEGIN"); |
| 699 speedtest1_prepare( |
| 700 "DELETE FROM t2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n |
| 701 ); |
| 702 for(i=1; i<=n; i++){ |
| 703 x1 = speedtest1_random()%maxb + 1; |
| 704 x2 = speedtest1_random()%10 + sz/5000 + x1; |
| 705 sqlite3_bind_int(g.pStmt, 1, x1); |
| 706 sqlite3_bind_int(g.pStmt, 2, x2); |
| 707 speedtest1_run(); |
| 708 } |
| 709 speedtest1_exec("COMMIT"); |
| 710 speedtest1_end_test(); |
| 711 |
| 712 |
| 713 n = sz; |
| 714 speedtest1_begin_test(280, "%d DELETEs of individual rows", n); |
| 715 speedtest1_exec("BEGIN"); |
| 716 speedtest1_prepare( |
| 717 "DELETE FROM t3 WHERE a=?1; -- %d times", n |
| 718 ); |
| 719 for(i=1; i<=n; i++){ |
| 720 x1 = speedtest1_random()%sz + 1; |
| 721 sqlite3_bind_int(g.pStmt, 1, x1); |
| 722 speedtest1_run(); |
| 723 } |
| 724 speedtest1_exec("COMMIT"); |
| 725 speedtest1_end_test(); |
| 726 |
| 727 |
| 728 speedtest1_begin_test(290, "Refill two %d-row tables using REPLACE", sz); |
| 729 speedtest1_exec("REPLACE INTO t2(a,b,c) SELECT a,b,c FROM t1"); |
| 730 speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM t1"); |
| 731 speedtest1_end_test(); |
| 732 |
| 733 speedtest1_begin_test(300, "Refill a %d-row table using (b&1)==(a&1)", sz); |
| 734 speedtest1_exec("DELETE FROM t2;"); |
| 735 speedtest1_exec("INSERT INTO t2(a,b,c)\n" |
| 736 " SELECT a,b,c FROM t1 WHERE (b&1)==(a&1);"); |
| 737 speedtest1_exec("INSERT INTO t2(a,b,c)\n" |
| 738 " SELECT a,b,c FROM t1 WHERE (b&1)<>(a&1);"); |
| 739 speedtest1_end_test(); |
| 740 |
| 741 |
| 742 n = sz/5; |
| 743 speedtest1_begin_test(310, "%d four-ways joins", n); |
| 744 speedtest1_exec("BEGIN"); |
| 745 speedtest1_prepare( |
| 746 "SELECT t1.c FROM t1, t2, t3, t4\n" |
| 747 " WHERE t4.a BETWEEN ?1 AND ?2\n" |
| 748 " AND t3.a=t4.b\n" |
| 749 " AND t2.a=t3.b\n" |
| 750 " AND t1.c=t2.c" |
| 751 ); |
| 752 for(i=1; i<=n; i++){ |
| 753 x1 = speedtest1_random()%sz + 1; |
| 754 x2 = speedtest1_random()%10 + x1 + 4; |
| 755 sqlite3_bind_int(g.pStmt, 1, x1); |
| 756 sqlite3_bind_int(g.pStmt, 2, x2); |
| 757 speedtest1_run(); |
| 758 } |
| 759 speedtest1_exec("COMMIT"); |
| 760 speedtest1_end_test(); |
| 761 |
| 762 speedtest1_begin_test(320, "subquery in result set", n); |
| 763 speedtest1_prepare( |
| 764 "SELECT sum(a), max(c),\n" |
| 765 " avg((SELECT a FROM t2 WHERE 5+t2.b=t1.b) AND rowid<?1), max(c)\n" |
| 766 " FROM t1 WHERE rowid<?1;" |
| 767 ); |
| 768 sqlite3_bind_int(g.pStmt, 1, est_square_root(g.szTest)*50); |
| 769 speedtest1_run(); |
| 770 speedtest1_end_test(); |
| 771 |
| 772 speedtest1_begin_test(980, "PRAGMA integrity_check"); |
| 773 speedtest1_exec("PRAGMA integrity_check"); |
| 774 speedtest1_end_test(); |
| 775 |
| 776 |
| 777 speedtest1_begin_test(990, "ANALYZE"); |
| 778 speedtest1_exec("ANALYZE"); |
| 779 speedtest1_end_test(); |
| 780 } |
| 781 |
| 782 /* |
| 783 ** A testset for common table expressions. This exercises code |
| 784 ** for views, subqueries, co-routines, etc. |
| 785 */ |
| 786 void testset_cte(void){ |
| 787 static const char *azPuzzle[] = { |
| 788 /* Easy */ |
| 789 "534...9.." |
| 790 "67.195..." |
| 791 ".98....6." |
| 792 "8...6...3" |
| 793 "4..8.3..1" |
| 794 "....2...6" |
| 795 ".6....28." |
| 796 "...419..5" |
| 797 "...28..79", |
| 798 |
| 799 /* Medium */ |
| 800 "53....9.." |
| 801 "6..195..." |
| 802 ".98....6." |
| 803 "8...6...3" |
| 804 "4..8.3..1" |
| 805 "....2...6" |
| 806 ".6....28." |
| 807 "...419..5" |
| 808 "....8..79", |
| 809 |
| 810 /* Hard */ |
| 811 "53......." |
| 812 "6..195..." |
| 813 ".98....6." |
| 814 "8...6...3" |
| 815 "4..8.3..1" |
| 816 "....2...6" |
| 817 ".6....28." |
| 818 "...419..5" |
| 819 "....8..79", |
| 820 }; |
| 821 const char *zPuz; |
| 822 double rSpacing; |
| 823 int nElem; |
| 824 |
| 825 if( g.szTest<25 ){ |
| 826 zPuz = azPuzzle[0]; |
| 827 }else if( g.szTest<70 ){ |
| 828 zPuz = azPuzzle[1]; |
| 829 }else{ |
| 830 zPuz = azPuzzle[2]; |
| 831 } |
| 832 speedtest1_begin_test(100, "Sudoku with recursive 'digits'"); |
| 833 speedtest1_prepare( |
| 834 "WITH RECURSIVE\n" |
| 835 " input(sud) AS (VALUES(?1)),\n" |
| 836 " digits(z,lp) AS (\n" |
| 837 " VALUES('1', 1)\n" |
| 838 " UNION ALL\n" |
| 839 " SELECT CAST(lp+1 AS TEXT), lp+1 FROM digits WHERE lp<9\n" |
| 840 " ),\n" |
| 841 " x(s, ind) AS (\n" |
| 842 " SELECT sud, instr(sud, '.') FROM input\n" |
| 843 " UNION ALL\n" |
| 844 " SELECT\n" |
| 845 " substr(s, 1, ind-1) || z || substr(s, ind+1),\n" |
| 846 " instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )\n" |
| 847 " FROM x, digits AS z\n" |
| 848 " WHERE ind>0\n" |
| 849 " AND NOT EXISTS (\n" |
| 850 " SELECT 1\n" |
| 851 " FROM digits AS lp\n" |
| 852 " WHERE z.z = substr(s, ((ind-1)/9)*9 + lp, 1)\n" |
| 853 " OR z.z = substr(s, ((ind-1)%%9) + (lp-1)*9 + 1, 1)\n" |
| 854 " OR z.z = substr(s, (((ind-1)/3) %% 3) * 3\n" |
| 855 " + ((ind-1)/27) * 27 + lp\n" |
| 856 " + ((lp-1) / 3) * 6, 1)\n" |
| 857 " )\n" |
| 858 " )\n" |
| 859 "SELECT s FROM x WHERE ind=0;" |
| 860 ); |
| 861 sqlite3_bind_text(g.pStmt, 1, zPuz, -1, SQLITE_STATIC); |
| 862 speedtest1_run(); |
| 863 speedtest1_end_test(); |
| 864 |
| 865 speedtest1_begin_test(200, "Sudoku with VALUES 'digits'"); |
| 866 speedtest1_prepare( |
| 867 "WITH RECURSIVE\n" |
| 868 " input(sud) AS (VALUES(?1)),\n" |
| 869 " digits(z,lp) AS (VALUES('1',1),('2',2),('3',3),('4',4),('5',5),\n" |
| 870 " ('6',6),('7',7),('8',8),('9',9)),\n" |
| 871 " x(s, ind) AS (\n" |
| 872 " SELECT sud, instr(sud, '.') FROM input\n" |
| 873 " UNION ALL\n" |
| 874 " SELECT\n" |
| 875 " substr(s, 1, ind-1) || z || substr(s, ind+1),\n" |
| 876 " instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )\n" |
| 877 " FROM x, digits AS z\n" |
| 878 " WHERE ind>0\n" |
| 879 " AND NOT EXISTS (\n" |
| 880 " SELECT 1\n" |
| 881 " FROM digits AS lp\n" |
| 882 " WHERE z.z = substr(s, ((ind-1)/9)*9 + lp, 1)\n" |
| 883 " OR z.z = substr(s, ((ind-1)%%9) + (lp-1)*9 + 1, 1)\n" |
| 884 " OR z.z = substr(s, (((ind-1)/3) %% 3) * 3\n" |
| 885 " + ((ind-1)/27) * 27 + lp\n" |
| 886 " + ((lp-1) / 3) * 6, 1)\n" |
| 887 " )\n" |
| 888 " )\n" |
| 889 "SELECT s FROM x WHERE ind=0;" |
| 890 ); |
| 891 sqlite3_bind_text(g.pStmt, 1, zPuz, -1, SQLITE_STATIC); |
| 892 speedtest1_run(); |
| 893 speedtest1_end_test(); |
| 894 |
| 895 rSpacing = 5.0/g.szTest; |
| 896 speedtest1_begin_test(300, "Mandelbrot Set with spacing=%f", rSpacing); |
| 897 speedtest1_prepare( |
| 898 "WITH RECURSIVE \n" |
| 899 " xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+?1 FROM xaxis WHERE x<1.2),\n
" |
| 900 " yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+?2 FROM yaxis WHERE y<1.0),\n
" |
| 901 " m(iter, cx, cy, x, y) AS (\n" |
| 902 " SELECT 0, x, y, 0.0, 0.0 FROM xaxis, yaxis\n" |
| 903 " UNION ALL\n" |
| 904 " SELECT iter+1, cx, cy, x*x-y*y + cx, 2.0*x*y + cy FROM m \n" |
| 905 " WHERE (x*x + y*y) < 4.0 AND iter<28\n" |
| 906 " ),\n" |
| 907 " m2(iter, cx, cy) AS (\n" |
| 908 " SELECT max(iter), cx, cy FROM m GROUP BY cx, cy\n" |
| 909 " ),\n" |
| 910 " a(t) AS (\n" |
| 911 " SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') \n" |
| 912 " FROM m2 GROUP BY cy\n" |
| 913 " )\n" |
| 914 "SELECT group_concat(rtrim(t),x'0a') FROM a;" |
| 915 ); |
| 916 sqlite3_bind_double(g.pStmt, 1, rSpacing*.05); |
| 917 sqlite3_bind_double(g.pStmt, 2, rSpacing); |
| 918 speedtest1_run(); |
| 919 speedtest1_end_test(); |
| 920 |
| 921 nElem = 10000*g.szTest; |
| 922 speedtest1_begin_test(400, "EXCEPT operator on %d-element tables", nElem); |
| 923 speedtest1_prepare( |
| 924 "WITH RECURSIVE \n" |
| 925 " t1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM t1 WHERE x<%d),\n" |
| 926 " t2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM t2 WHERE y<%d)\n" |
| 927 "SELECT count(x), avg(x) FROM (\n" |
| 928 " SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1\n" |
| 929 ");", |
| 930 nElem, nElem |
| 931 ); |
| 932 speedtest1_run(); |
| 933 speedtest1_end_test(); |
| 934 |
| 935 } |
| 936 |
| 937 #ifdef SQLITE_ENABLE_RTREE |
| 938 /* Generate two numbers between 1 and mx. The first number is less than |
| 939 ** the second. Usually the numbers are near each other but can sometimes |
| 940 ** be far apart. |
| 941 */ |
| 942 static void twoCoords( |
| 943 int p1, int p2, /* Parameters adjusting sizes */ |
| 944 unsigned mx, /* Range of 1..mx */ |
| 945 unsigned *pX0, unsigned *pX1 /* OUT: write results here */ |
| 946 ){ |
| 947 unsigned d, x0, x1, span; |
| 948 |
| 949 span = mx/100 + 1; |
| 950 if( speedtest1_random()%3==0 ) span *= p1; |
| 951 if( speedtest1_random()%p2==0 ) span = mx/2; |
| 952 d = speedtest1_random()%span + 1; |
| 953 x0 = speedtest1_random()%(mx-d) + 1; |
| 954 x1 = x0 + d; |
| 955 *pX0 = x0; |
| 956 *pX1 = x1; |
| 957 } |
| 958 #endif |
| 959 |
| 960 #ifdef SQLITE_ENABLE_RTREE |
| 961 /* The following routine is an R-Tree geometry callback. It returns |
| 962 ** true if the object overlaps a slice on the Y coordinate between the |
| 963 ** two values given as arguments. In other words |
| 964 ** |
| 965 ** SELECT count(*) FROM rt1 WHERE id MATCH xslice(10,20); |
| 966 ** |
| 967 ** Is the same as saying: |
| 968 ** |
| 969 ** SELECT count(*) FROM rt1 WHERE y1>=10 AND y0<=20; |
| 970 */ |
| 971 static int xsliceGeometryCallback( |
| 972 sqlite3_rtree_geometry *p, |
| 973 int nCoord, |
| 974 double *aCoord, |
| 975 int *pRes |
| 976 ){ |
| 977 *pRes = aCoord[3]>=p->aParam[0] && aCoord[2]<=p->aParam[1]; |
| 978 return SQLITE_OK; |
| 979 } |
| 980 #endif /* SQLITE_ENABLE_RTREE */ |
| 981 |
| 982 #ifdef SQLITE_ENABLE_RTREE |
| 983 /* |
| 984 ** A testset for the R-Tree virtual table |
| 985 */ |
| 986 void testset_rtree(int p1, int p2){ |
| 987 unsigned i, n; |
| 988 unsigned mxCoord; |
| 989 unsigned x0, x1, y0, y1, z0, z1; |
| 990 unsigned iStep; |
| 991 int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*100 ); |
| 992 |
| 993 mxCoord = 15000; |
| 994 n = g.szTest*100; |
| 995 speedtest1_begin_test(100, "%d INSERTs into an r-tree", n); |
| 996 speedtest1_exec("BEGIN"); |
| 997 speedtest1_exec("CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1,z0,z1)"); |
| 998 speedtest1_prepare("INSERT INTO rt1(id,x0,x1,y0,y1,z0,z1)" |
| 999 "VALUES(?1,?2,?3,?4,?5,?6,?7)"); |
| 1000 for(i=1; i<=n; i++){ |
| 1001 twoCoords(p1, p2, mxCoord, &x0, &x1); |
| 1002 twoCoords(p1, p2, mxCoord, &y0, &y1); |
| 1003 twoCoords(p1, p2, mxCoord, &z0, &z1); |
| 1004 sqlite3_bind_int(g.pStmt, 1, i); |
| 1005 sqlite3_bind_int(g.pStmt, 2, x0); |
| 1006 sqlite3_bind_int(g.pStmt, 3, x1); |
| 1007 sqlite3_bind_int(g.pStmt, 4, y0); |
| 1008 sqlite3_bind_int(g.pStmt, 5, y1); |
| 1009 sqlite3_bind_int(g.pStmt, 6, z0); |
| 1010 sqlite3_bind_int(g.pStmt, 7, z1); |
| 1011 speedtest1_run(); |
| 1012 } |
| 1013 speedtest1_exec("COMMIT"); |
| 1014 speedtest1_end_test(); |
| 1015 |
| 1016 speedtest1_begin_test(101, "Copy from rtree to a regular table"); |
| 1017 speedtest1_exec("CREATE TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)"); |
| 1018 speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1"); |
| 1019 speedtest1_end_test(); |
| 1020 |
| 1021 n = g.szTest*20; |
| 1022 speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n); |
| 1023 speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2"); |
| 1024 iStep = mxCoord/n; |
| 1025 for(i=0; i<n; i++){ |
| 1026 sqlite3_bind_int(g.pStmt, 1, i*iStep); |
| 1027 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); |
| 1028 speedtest1_run(); |
| 1029 aCheck[i] = atoi(g.zResult); |
| 1030 } |
| 1031 speedtest1_end_test(); |
| 1032 |
| 1033 if( g.bVerify ){ |
| 1034 n = g.szTest*20; |
| 1035 speedtest1_begin_test(111, "Verify result from 1-D intersect slice queries")
; |
| 1036 speedtest1_prepare("SELECT count(*) FROM t1 WHERE x0>=?1 AND x1<=?2"); |
| 1037 iStep = mxCoord/n; |
| 1038 for(i=0; i<n; i++){ |
| 1039 sqlite3_bind_int(g.pStmt, 1, i*iStep); |
| 1040 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); |
| 1041 speedtest1_run(); |
| 1042 if( aCheck[i]!=atoi(g.zResult) ){ |
| 1043 fatal_error("Count disagree step %d: %d..%d. %d vs %d", |
| 1044 i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult)); |
| 1045 } |
| 1046 } |
| 1047 speedtest1_end_test(); |
| 1048 } |
| 1049 |
| 1050 n = g.szTest*20; |
| 1051 speedtest1_begin_test(120, "%d one-dimensional overlap slice queries", n); |
| 1052 speedtest1_prepare("SELECT count(*) FROM rt1 WHERE y1>=?1 AND y0<=?2"); |
| 1053 iStep = mxCoord/n; |
| 1054 for(i=0; i<n; i++){ |
| 1055 sqlite3_bind_int(g.pStmt, 1, i*iStep); |
| 1056 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); |
| 1057 speedtest1_run(); |
| 1058 aCheck[i] = atoi(g.zResult); |
| 1059 } |
| 1060 speedtest1_end_test(); |
| 1061 |
| 1062 if( g.bVerify ){ |
| 1063 n = g.szTest*20; |
| 1064 speedtest1_begin_test(121, "Verify result from 1-D overlap slice queries"); |
| 1065 speedtest1_prepare("SELECT count(*) FROM t1 WHERE y1>=?1 AND y0<=?2"); |
| 1066 iStep = mxCoord/n; |
| 1067 for(i=0; i<n; i++){ |
| 1068 sqlite3_bind_int(g.pStmt, 1, i*iStep); |
| 1069 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); |
| 1070 speedtest1_run(); |
| 1071 if( aCheck[i]!=atoi(g.zResult) ){ |
| 1072 fatal_error("Count disagree step %d: %d..%d. %d vs %d", |
| 1073 i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult)); |
| 1074 } |
| 1075 } |
| 1076 speedtest1_end_test(); |
| 1077 } |
| 1078 |
| 1079 |
| 1080 n = g.szTest*20; |
| 1081 speedtest1_begin_test(125, "%d custom geometry callback queries", n); |
| 1082 sqlite3_rtree_geometry_callback(g.db, "xslice", xsliceGeometryCallback, 0); |
| 1083 speedtest1_prepare("SELECT count(*) FROM rt1 WHERE id MATCH xslice(?1,?2)"); |
| 1084 iStep = mxCoord/n; |
| 1085 for(i=0; i<n; i++){ |
| 1086 sqlite3_bind_int(g.pStmt, 1, i*iStep); |
| 1087 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); |
| 1088 speedtest1_run(); |
| 1089 if( aCheck[i]!=atoi(g.zResult) ){ |
| 1090 fatal_error("Count disagree step %d: %d..%d. %d vs %d", |
| 1091 i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult)); |
| 1092 } |
| 1093 } |
| 1094 speedtest1_end_test(); |
| 1095 |
| 1096 n = g.szTest*80; |
| 1097 speedtest1_begin_test(130, "%d three-dimensional intersect box queries", n); |
| 1098 speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x1>=?1 AND x0<=?2" |
| 1099 " AND y1>=?1 AND y0<=?2 AND z1>=?1 AND z0<=?2"); |
| 1100 iStep = mxCoord/n; |
| 1101 for(i=0; i<n; i++){ |
| 1102 sqlite3_bind_int(g.pStmt, 1, i*iStep); |
| 1103 sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep); |
| 1104 speedtest1_run(); |
| 1105 aCheck[i] = atoi(g.zResult); |
| 1106 } |
| 1107 speedtest1_end_test(); |
| 1108 |
| 1109 n = g.szTest*100; |
| 1110 speedtest1_begin_test(140, "%d rowid queries", n); |
| 1111 speedtest1_prepare("SELECT * FROM rt1 WHERE id=?1"); |
| 1112 for(i=1; i<=n; i++){ |
| 1113 sqlite3_bind_int(g.pStmt, 1, i); |
| 1114 speedtest1_run(); |
| 1115 } |
| 1116 speedtest1_end_test(); |
| 1117 } |
| 1118 #endif /* SQLITE_ENABLE_RTREE */ |
| 1119 |
| 1120 /* |
| 1121 ** A testset used for debugging speedtest1 itself. |
| 1122 */ |
| 1123 void testset_debug1(void){ |
| 1124 unsigned i, n; |
| 1125 unsigned x1, x2; |
| 1126 char zNum[2000]; /* A number name */ |
| 1127 |
| 1128 n = g.szTest; |
| 1129 for(i=1; i<=n; i++){ |
| 1130 x1 = swizzle(i, n); |
| 1131 x2 = swizzle(x1, n); |
| 1132 speedtest1_numbername(x1, zNum, sizeof(zNum)); |
| 1133 printf("%5d %5d %5d %s\n", i, x1, x2, zNum); |
| 1134 } |
| 1135 } |
| 1136 |
| 1137 int main(int argc, char **argv){ |
| 1138 int doAutovac = 0; /* True for --autovacuum */ |
| 1139 int cacheSize = 0; /* Desired cache size. 0 means default */ |
| 1140 int doExclusive = 0; /* True for --exclusive */ |
| 1141 int nHeap = 0, mnHeap = 0; /* Heap size from --heap */ |
| 1142 int doIncrvac = 0; /* True for --incrvacuum */ |
| 1143 const char *zJMode = 0; /* Journal mode */ |
| 1144 const char *zKey = 0; /* Encryption key */ |
| 1145 int nLook = 0, szLook = 0; /* --lookaside configuration */ |
| 1146 int noSync = 0; /* True for --nosync */ |
| 1147 int pageSize = 0; /* Desired page size. 0 means default */ |
| 1148 int nPCache = 0, szPCache = 0;/* --pcache configuration */ |
| 1149 int nScratch = 0, szScratch=0;/* --scratch configuration */ |
| 1150 int showStats = 0; /* True for --stats */ |
| 1151 int nThread = 0; /* --threads value */ |
| 1152 const char *zTSet = "main"; /* Which --testset torun */ |
| 1153 int doTrace = 0; /* True for --trace */ |
| 1154 const char *zEncoding = 0; /* --utf16be or --utf16le */ |
| 1155 const char *zDbName = 0; /* Name of the test database */ |
| 1156 |
| 1157 void *pHeap = 0; /* Allocated heap space */ |
| 1158 void *pLook = 0; /* Allocated lookaside space */ |
| 1159 void *pPCache = 0; /* Allocated storage for pcache */ |
| 1160 void *pScratch = 0; /* Allocated storage for scratch */ |
| 1161 int iCur, iHi; /* Stats values, current and "highwater" */ |
| 1162 int i; /* Loop counter */ |
| 1163 int rc; /* API return code */ |
| 1164 |
| 1165 /* Process command-line arguments */ |
| 1166 g.zWR = ""; |
| 1167 g.zNN = ""; |
| 1168 g.zPK = "UNIQUE"; |
| 1169 g.szTest = 100; |
| 1170 for(i=1; i<argc; i++){ |
| 1171 const char *z = argv[i]; |
| 1172 if( z[0]=='-' ){ |
| 1173 do{ z++; }while( z[0]=='-' ); |
| 1174 if( strcmp(z,"autovacuum")==0 ){ |
| 1175 doAutovac = 1; |
| 1176 }else if( strcmp(z,"cachesize")==0 ){ |
| 1177 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); |
| 1178 i++; |
| 1179 cacheSize = integerValue(argv[i]); |
| 1180 }else if( strcmp(z,"exclusive")==0 ){ |
| 1181 doExclusive = 1; |
| 1182 }else if( strcmp(z,"explain")==0 ){ |
| 1183 g.bSqlOnly = 1; |
| 1184 g.bExplain = 1; |
| 1185 }else if( strcmp(z,"heap")==0 ){ |
| 1186 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); |
| 1187 nHeap = integerValue(argv[i+1]); |
| 1188 mnHeap = integerValue(argv[i+2]); |
| 1189 i += 2; |
| 1190 }else if( strcmp(z,"incrvacuum")==0 ){ |
| 1191 doIncrvac = 1; |
| 1192 }else if( strcmp(z,"journal")==0 ){ |
| 1193 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); |
| 1194 zJMode = argv[++i]; |
| 1195 }else if( strcmp(z,"key")==0 ){ |
| 1196 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); |
| 1197 zKey = argv[++i]; |
| 1198 }else if( strcmp(z,"lookaside")==0 ){ |
| 1199 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); |
| 1200 nLook = integerValue(argv[i+1]); |
| 1201 szLook = integerValue(argv[i+2]); |
| 1202 i += 2; |
| 1203 }else if( strcmp(z,"nosync")==0 ){ |
| 1204 noSync = 1; |
| 1205 }else if( strcmp(z,"notnull")==0 ){ |
| 1206 g.zNN = "NOT NULL"; |
| 1207 }else if( strcmp(z,"pagesize")==0 ){ |
| 1208 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); |
| 1209 pageSize = integerValue(argv[++i]); |
| 1210 }else if( strcmp(z,"pcache")==0 ){ |
| 1211 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); |
| 1212 nPCache = integerValue(argv[i+1]); |
| 1213 szPCache = integerValue(argv[i+2]); |
| 1214 i += 2; |
| 1215 }else if( strcmp(z,"primarykey")==0 ){ |
| 1216 g.zPK = "PRIMARY KEY"; |
| 1217 }else if( strcmp(z,"reprepare")==0 ){ |
| 1218 g.bReprepare = 1; |
| 1219 }else if( strcmp(z,"scratch")==0 ){ |
| 1220 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); |
| 1221 nScratch = integerValue(argv[i+1]); |
| 1222 szScratch = integerValue(argv[i+2]); |
| 1223 i += 2; |
| 1224 }else if( strcmp(z,"sqlonly")==0 ){ |
| 1225 g.bSqlOnly = 1; |
| 1226 }else if( strcmp(z,"size")==0 ){ |
| 1227 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); |
| 1228 g.szTest = integerValue(argv[++i]); |
| 1229 }else if( strcmp(z,"stats")==0 ){ |
| 1230 showStats = 1; |
| 1231 }else if( strcmp(z,"testset")==0 ){ |
| 1232 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); |
| 1233 zTSet = argv[++i]; |
| 1234 }else if( strcmp(z,"trace")==0 ){ |
| 1235 doTrace = 1; |
| 1236 }else if( strcmp(z,"threads")==0 ){ |
| 1237 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); |
| 1238 nThread = integerValue(argv[++i]); |
| 1239 }else if( strcmp(z,"utf16le")==0 ){ |
| 1240 zEncoding = "utf16le"; |
| 1241 }else if( strcmp(z,"utf16be")==0 ){ |
| 1242 zEncoding = "utf16be"; |
| 1243 }else if( strcmp(z,"verify")==0 ){ |
| 1244 g.bVerify = 1; |
| 1245 }else if( strcmp(z,"without-rowid")==0 ){ |
| 1246 g.zWR = "WITHOUT ROWID"; |
| 1247 g.zPK = "PRIMARY KEY"; |
| 1248 }else if( strcmp(z, "help")==0 || strcmp(z,"?")==0 ){ |
| 1249 printf(zHelp, argv[0]); |
| 1250 exit(0); |
| 1251 }else{ |
| 1252 fatal_error("unknown option: %s\nUse \"%s -?\" for help\n", |
| 1253 argv[i], argv[0]); |
| 1254 } |
| 1255 }else if( zDbName==0 ){ |
| 1256 zDbName = argv[i]; |
| 1257 }else{ |
| 1258 fatal_error("surplus argument: %s\nUse \"%s -?\" for help\n", |
| 1259 argv[i], argv[0]); |
| 1260 } |
| 1261 } |
| 1262 #if 0 |
| 1263 if( zDbName==0 ){ |
| 1264 fatal_error(zHelp, argv[0]); |
| 1265 } |
| 1266 #endif |
| 1267 if( nHeap>0 ){ |
| 1268 pHeap = malloc( nHeap ); |
| 1269 if( pHeap==0 ) fatal_error("cannot allocate %d-byte heap\n", nHeap); |
| 1270 rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap); |
| 1271 if( rc ) fatal_error("heap configuration failed: %d\n", rc); |
| 1272 } |
| 1273 if( nPCache>0 && szPCache>0 ){ |
| 1274 pPCache = malloc( nPCache*(sqlite3_int64)szPCache ); |
| 1275 if( pPCache==0 ) fatal_error("cannot allocate %lld-byte pcache\n", |
| 1276 nPCache*(sqlite3_int64)szPCache); |
| 1277 rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache); |
| 1278 if( rc ) fatal_error("pcache configuration failed: %d\n", rc); |
| 1279 } |
| 1280 if( nScratch>0 && szScratch>0 ){ |
| 1281 pScratch = malloc( nScratch*(sqlite3_int64)szScratch ); |
| 1282 if( pScratch==0 ) fatal_error("cannot allocate %lld-byte scratch\n", |
| 1283 nScratch*(sqlite3_int64)szScratch); |
| 1284 rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch); |
| 1285 if( rc ) fatal_error("scratch configuration failed: %d\n", rc); |
| 1286 } |
| 1287 if( nLook>0 ){ |
| 1288 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0); |
| 1289 } |
| 1290 |
| 1291 /* Open the database and the input file */ |
| 1292 if( sqlite3_open(zDbName, &g.db) ){ |
| 1293 fatal_error("Cannot open database file: %s\n", zDbName); |
| 1294 } |
| 1295 if( nLook>0 && szLook>0 ){ |
| 1296 pLook = malloc( nLook*szLook ); |
| 1297 rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook,nLook)
; |
| 1298 if( rc ) fatal_error("lookaside configuration failed: %d\n", rc); |
| 1299 } |
| 1300 |
| 1301 /* Set database connection options */ |
| 1302 sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0); |
| 1303 if( doTrace ) sqlite3_trace(g.db, traceCallback, 0); |
| 1304 speedtest1_exec("PRAGMA threads=%d", nThread); |
| 1305 if( zKey ){ |
| 1306 speedtest1_exec("PRAGMA key('%s')", zKey); |
| 1307 } |
| 1308 if( zEncoding ){ |
| 1309 speedtest1_exec("PRAGMA encoding=%s", zEncoding); |
| 1310 } |
| 1311 if( doAutovac ){ |
| 1312 speedtest1_exec("PRAGMA auto_vacuum=FULL"); |
| 1313 }else if( doIncrvac ){ |
| 1314 speedtest1_exec("PRAGMA auto_vacuum=INCREMENTAL"); |
| 1315 } |
| 1316 if( pageSize ){ |
| 1317 speedtest1_exec("PRAGMA page_size=%d", pageSize); |
| 1318 } |
| 1319 if( cacheSize ){ |
| 1320 speedtest1_exec("PRAGMA cache_size=%d", cacheSize); |
| 1321 } |
| 1322 if( noSync ) speedtest1_exec("PRAGMA synchronous=OFF"); |
| 1323 if( doExclusive ){ |
| 1324 speedtest1_exec("PRAGMA locking_mode=EXCLUSIVE"); |
| 1325 } |
| 1326 if( zJMode ){ |
| 1327 speedtest1_exec("PRAGMA journal_mode=%s", zJMode); |
| 1328 } |
| 1329 |
| 1330 if( g.bExplain ) printf(".explain\n.echo on\n"); |
| 1331 if( strcmp(zTSet,"main")==0 ){ |
| 1332 testset_main(); |
| 1333 }else if( strcmp(zTSet,"debug1")==0 ){ |
| 1334 testset_debug1(); |
| 1335 }else if( strcmp(zTSet,"cte")==0 ){ |
| 1336 testset_cte(); |
| 1337 }else if( strcmp(zTSet,"rtree")==0 ){ |
| 1338 #ifdef SQLITE_ENABLE_RTREE |
| 1339 testset_rtree(6, 147); |
| 1340 #else |
| 1341 fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable " |
| 1342 "the R-Tree tests\n"); |
| 1343 #endif |
| 1344 }else{ |
| 1345 fatal_error("unknown testset: \"%s\"\nChoices: main debug1 cte rtree\n", |
| 1346 zTSet); |
| 1347 } |
| 1348 speedtest1_final(); |
| 1349 |
| 1350 /* Database connection statistics printed after both prepared statements |
| 1351 ** have been finalized */ |
| 1352 #if SQLITE_VERSION_NUMBER>=3007009 |
| 1353 if( showStats ){ |
| 1354 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHi, 0); |
| 1355 printf("-- Lookaside Slots Used: %d (max %d)\n", iCur,iHi); |
| 1356 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHi, 0); |
| 1357 printf("-- Successful lookasides: %d\n", iHi); |
| 1358 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHi,0); |
| 1359 printf("-- Lookaside size faults: %d\n", iHi); |
| 1360 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHi,0); |
| 1361 printf("-- Lookaside OOM faults: %d\n", iHi); |
| 1362 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHi, 0); |
| 1363 printf("-- Pager Heap Usage: %d bytes\n", iCur); |
| 1364 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHi, 1); |
| 1365 printf("-- Page cache hits: %d\n", iCur); |
| 1366 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHi, 1); |
| 1367 printf("-- Page cache misses: %d\n", iCur); |
| 1368 #if SQLITE_VERSION_NUMBER>=3007012 |
| 1369 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHi, 1); |
| 1370 printf("-- Page cache writes: %d\n", iCur); |
| 1371 #endif |
| 1372 sqlite3_db_status(g.db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHi, 0); |
| 1373 printf("-- Schema Heap Usage: %d bytes\n", iCur); |
| 1374 sqlite3_db_status(g.db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHi, 0); |
| 1375 printf("-- Statement Heap Usage: %d bytes\n", iCur); |
| 1376 } |
| 1377 #endif |
| 1378 |
| 1379 sqlite3_close(g.db); |
| 1380 |
| 1381 /* Global memory usage statistics printed after the database connection |
| 1382 ** has closed. Memory usage should be zero at this point. */ |
| 1383 if( showStats ){ |
| 1384 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHi, 0); |
| 1385 printf("-- Memory Used (bytes): %d (max %d)\n", iCur,iHi); |
| 1386 #if SQLITE_VERSION_NUMBER>=3007000 |
| 1387 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHi, 0); |
| 1388 printf("-- Outstanding Allocations: %d (max %d)\n", iCur,iHi); |
| 1389 #endif |
| 1390 sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0); |
| 1391 printf("-- Pcache Overflow Bytes: %d (max %d)\n", iCur,iHi); |
| 1392 sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHi, 0); |
| 1393 printf("-- Scratch Overflow Bytes: %d (max %d)\n", iCur,iHi); |
| 1394 sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0); |
| 1395 printf("-- Largest Allocation: %d bytes\n",iHi); |
| 1396 sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0); |
| 1397 printf("-- Largest Pcache Allocation: %d bytes\n",iHi); |
| 1398 sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHi, 0); |
| 1399 printf("-- Largest Scratch Allocation: %d bytes\n", iHi); |
| 1400 } |
| 1401 |
| 1402 /* Release memory */ |
| 1403 free( pLook ); |
| 1404 free( pPCache ); |
| 1405 free( pScratch ); |
| 1406 free( pHeap ); |
| 1407 return 0; |
| 1408 } |
OLD | NEW |