blob: f3e79ec8169f011209220cc97936e067562e50eb [file] [log] [blame]
drhad1ca9a2013-11-23 04:16:58 +00001/*
2** A program for performance testing.
3**
4** The available command-line options are described below:
5*/
6static 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"
drh93307e92013-11-24 01:14:14 +000012 " --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
drhad1ca9a2013-11-23 04:16:58 +000013 " --incrvacuum Enable incremenatal vacuum mode\n"
14 " --journalmode M Set the journal_mode to MODE\n"
15 " --key KEY Set the encryption key to KEY\n"
16 " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
17 " --nosync Set PRAGMA synchronous=OFF\n"
18 " --notnull Add NOT NULL constraints to table columns\n"
19 " --pagesize N Set the page size to N\n"
20 " --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
21 " --primarykey Use PRIMARY KEY instead of UNIQUE where appropriate\n"
22 " --reprepare Reprepare each statement upon every invocation\n"
drh93307e92013-11-24 01:14:14 +000023 " --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
drhad1ca9a2013-11-23 04:16:58 +000024 " --sqlonly No-op. Only show the SQL that would have been run.\n"
25 " --size N Relative test size. Default=100\n"
26 " --stats Show statistics at the end\n"
27 " --testset T Run test-set T\n"
28 " --trace Turn on SQL tracing\n"
29 " --utf16be Set text encoding to UTF-16BE\n"
30 " --utf16le Set text encoding to UTF-16LE\n"
31 " --without-rowid Use WITHOUT ROWID where appropriate\n"
32;
33
34
35#include "sqlite3.h"
36#include <assert.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <stdarg.h>
40#include <string.h>
41#include <ctype.h>
42
43/* All global state is held in this structure */
44static struct Global {
45 sqlite3 *db; /* The open database connection */
46 sqlite3_stmt *pStmt; /* Current SQL statement */
47 sqlite3_int64 iStart; /* Start-time for the current test */
48 sqlite3_int64 iTotal; /* Total time */
49 int bWithoutRowid; /* True for --without-rowid */
50 int bReprepare; /* True to reprepare the SQL on each rerun */
51 int bSqlOnly; /* True to print the SQL once only */
52 int szTest; /* Scale factor for test iterations */
53 const char *zWR; /* Might be WITHOUT ROWID */
54 const char *zNN; /* Might be NOT NULL */
55 const char *zPK; /* Might be UNIQUE or PRIMARY KEY */
56 unsigned int x, y; /* Pseudo-random number generator state */
57 int nResult; /* Size of the current result */
58 char zResult[3000]; /* Text of the current result */
59} g;
60
drhad1ca9a2013-11-23 04:16:58 +000061
drh93307e92013-11-24 01:14:14 +000062/* Print an error message and exit */
63static void fatal_error(const char *zMsg, ...){
64 va_list ap;
65 va_start(ap, zMsg);
66 vfprintf(stderr, zMsg, ap);
67 va_end(ap);
68 exit(1);
drhad1ca9a2013-11-23 04:16:58 +000069}
70
71/*
72** Return the value of a hexadecimal digit. Return -1 if the input
73** is not a hex digit.
74*/
75static int hexDigitValue(char c){
76 if( c>='0' && c<='9' ) return c - '0';
77 if( c>='a' && c<='f' ) return c - 'a' + 10;
78 if( c>='A' && c<='F' ) return c - 'A' + 10;
79 return -1;
80}
81
drh290ea402013-12-01 18:10:01 +000082/* Provide an alternative to sqlite3_stricmp() in older versions of
83** SQLite */
84#if SQLITE_VERSION_NUMBER<3007011
85# define sqlite3_stricmp strcmp
86#endif
87
drhad1ca9a2013-11-23 04:16:58 +000088/*
89** Interpret zArg as an integer value, possibly with suffixes.
90*/
drh93307e92013-11-24 01:14:14 +000091static int integerValue(const char *zArg){
drhad1ca9a2013-11-23 04:16:58 +000092 sqlite3_int64 v = 0;
93 static const struct { char *zSuffix; int iMult; } aMult[] = {
94 { "KiB", 1024 },
95 { "MiB", 1024*1024 },
96 { "GiB", 1024*1024*1024 },
97 { "KB", 1000 },
98 { "MB", 1000000 },
99 { "GB", 1000000000 },
100 { "K", 1000 },
101 { "M", 1000000 },
102 { "G", 1000000000 },
103 };
104 int i;
105 int isNeg = 0;
106 if( zArg[0]=='-' ){
107 isNeg = 1;
108 zArg++;
109 }else if( zArg[0]=='+' ){
110 zArg++;
111 }
112 if( zArg[0]=='0' && zArg[1]=='x' ){
113 int x;
114 zArg += 2;
115 while( (x = hexDigitValue(zArg[0]))>=0 ){
116 v = (v<<4) + x;
117 zArg++;
118 }
119 }else{
120 while( isdigit(zArg[0]) ){
121 v = v*10 + zArg[0] - '0';
122 zArg++;
123 }
124 }
125 for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
126 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
127 v *= aMult[i].iMult;
128 break;
129 }
130 }
mistachkinb87875a2013-11-27 18:00:20 +0000131 if( v>0x7fffffff ) fatal_error("parameter too large - max 2147483648");
drhdcb5fa02013-11-27 14:50:51 +0000132 return (int)(isNeg? -v : v);
drhad1ca9a2013-11-23 04:16:58 +0000133}
134
135/* Return the current wall-clock time, in milliseconds */
136sqlite3_int64 speedtest1_timestamp(void){
137 static sqlite3_vfs *clockVfs = 0;
138 sqlite3_int64 t;
139 if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
drhd79e9c52013-12-02 01:24:05 +0000140#if SQLITE_VERSION_NUMBER>=3007000
drh290ea402013-12-01 18:10:01 +0000141 if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
drhad1ca9a2013-11-23 04:16:58 +0000142 clockVfs->xCurrentTimeInt64(clockVfs, &t);
drhd79e9c52013-12-02 01:24:05 +0000143 }else
144#endif
145 {
drhad1ca9a2013-11-23 04:16:58 +0000146 double r;
147 clockVfs->xCurrentTime(clockVfs, &r);
148 t = (sqlite3_int64)(r*86400000.0);
149 }
150 return t;
151}
152
153/* Return a pseudo-random unsigned integer */
154unsigned int speedtest1_random(void){
155 g.x = (g.x>>1) ^ ((1+~(g.x&1)) & 0xd0000001);
156 g.y = g.y*1103515245 + 12345;
157 return g.x ^ g.y;
158}
159
160/* Map the value in within the range of 1...limit into another
161** number in a way that is chatic and invertable.
162*/
163unsigned swizzle(unsigned in, unsigned limit){
164 unsigned out = 0;
165 while( limit ){
166 out = (out<<1) | (in&1);
167 in >>= 1;
168 limit >>= 1;
169 }
170 return out;
171}
172
173/* Round up a number so that it is a power of two minus one
174*/
175unsigned roundup_allones(unsigned limit){
176 unsigned m = 1;
177 while( m<limit ) m = (m<<1)+1;
178 return m;
179}
180
181/* The speedtest1_numbername procedure below converts its argment (an integer)
182** into a string which is the English-language name for that number.
183** The returned string should be freed with sqlite3_free().
184**
185** Example:
186**
187** speedtest1_numbername(123) -> "one hundred twenty three"
188*/
189int speedtest1_numbername(unsigned int n, char *zOut, int nOut){
190 static const char *ones[] = { "zero", "one", "two", "three", "four", "five",
191 "six", "seven", "eight", "nine", "ten", "eleven", "twelve",
192 "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
193 "eighteen", "nineteen" };
194 static const char *tens[] = { "", "ten", "twenty", "thirty", "forty",
195 "fifty", "sixty", "seventy", "eighty", "ninety" };
196 int i = 0;
197
198 if( n>=1000000000 ){
199 i += speedtest1_numbername(n/1000000000, zOut+i, nOut-i);
200 sqlite3_snprintf(nOut-i, zOut+i, " billion");
201 i += (int)strlen(zOut+i);
202 n = n % 1000000000;
203 }
204 if( n>=1000000 ){
205 if( i && i<nOut-1 ) zOut[i++] = ' ';
206 i += speedtest1_numbername(n/1000000, zOut+i, nOut-i);
207 sqlite3_snprintf(nOut-i, zOut+i, " million");
208 i += (int)strlen(zOut+i);
209 n = n % 1000000;
210 }
211 if( n>=1000 ){
212 if( i && i<nOut-1 ) zOut[i++] = ' ';
213 i += speedtest1_numbername(n/1000, zOut+i, nOut-i);
214 sqlite3_snprintf(nOut-i, zOut+i, " thousand");
215 i += (int)strlen(zOut+i);
216 n = n % 1000;
217 }
218 if( n>=100 ){
219 if( i && i<nOut-1 ) zOut[i++] = ' ';
220 sqlite3_snprintf(nOut-i, zOut+i, "%s hundred", ones[n/100]);
221 i += (int)strlen(zOut+i);
222 n = n % 100;
223 }
224 if( n>=20 ){
225 if( i && i<nOut-1 ) zOut[i++] = ' ';
226 sqlite3_snprintf(nOut-i, zOut+i, "%s", tens[n/10]);
227 i += (int)strlen(zOut+i);
228 n = n % 10;
229 }
230 if( n>0 ){
231 if( i && i<nOut-1 ) zOut[i++] = ' ';
232 sqlite3_snprintf(nOut-i, zOut+i, "%s", ones[n]);
233 i += (int)strlen(zOut+i);
234 }
235 if( i==0 ){
236 sqlite3_snprintf(nOut-i, zOut+i, "zero");
237 i += (int)strlen(zOut+i);
238 }
239 return i;
240}
241
242
243/* Start a new test case */
244#define NAMEWIDTH 60
245static const char zDots[] =
246 ".......................................................................";
247void speedtest1_begin_test(int iTestNum, const char *zTestName, ...){
248 int n = (int)strlen(zTestName);
249 char *zName;
250 va_list ap;
251 va_start(ap, zTestName);
252 zName = sqlite3_vmprintf(zTestName, ap);
253 va_end(ap);
254 n = (int)strlen(zName);
255 if( n>NAMEWIDTH ){
256 zName[NAMEWIDTH] = 0;
257 n = NAMEWIDTH;
258 }
259 if( g.bSqlOnly ){
260 printf("/* %4d - %s%.*s */\n", iTestNum, zName, NAMEWIDTH-n, zDots);
261 }else{
262 printf("%4d - %s%.*s ", iTestNum, zName, NAMEWIDTH-n, zDots);
263 fflush(stdout);
264 }
265 sqlite3_free(zName);
266 g.nResult = 0;
267 g.iStart = speedtest1_timestamp();
drhdcb5fa02013-11-27 14:50:51 +0000268 g.x = 0xad131d0b;
269 g.y = 0x44f9eac8;
drhad1ca9a2013-11-23 04:16:58 +0000270}
271
272/* Complete a test case */
273void speedtest1_end_test(void){
274 sqlite3_int64 iElapseTime = speedtest1_timestamp() - g.iStart;
275 if( !g.bSqlOnly ){
276 g.iTotal += iElapseTime;
277 printf("%4d.%03ds\n", (int)(iElapseTime/1000), (int)(iElapseTime%1000));
278 }
279 if( g.pStmt ){
280 sqlite3_finalize(g.pStmt);
281 g.pStmt = 0;
282 }
283}
284
285/* Report end of testing */
286void speedtest1_final(void){
287 if( !g.bSqlOnly ){
288 printf(" TOTAL%.*s %4d.%03ds\n", NAMEWIDTH-5, zDots,
289 (int)(g.iTotal/1000), (int)(g.iTotal%1000));
290 }
291}
292
drhad1ca9a2013-11-23 04:16:58 +0000293/* Run SQL */
294void speedtest1_exec(const char *zFormat, ...){
295 va_list ap;
296 char *zSql;
297 va_start(ap, zFormat);
298 zSql = sqlite3_vmprintf(zFormat, ap);
299 va_end(ap);
300 if( g.bSqlOnly ){
301 int n = (int)strlen(zSql);
302 while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; }
303 printf("%.*s;\n", n, zSql);
304 }else{
drhe19f8322013-11-23 11:45:58 +0000305 char *zErrMsg = 0;
306 int rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
307 if( zErrMsg ) fatal_error("SQL error: %s\n%s\n", zErrMsg, zSql);
308 if( rc!=SQLITE_OK ) fatal_error("exec error: %s\n", sqlite3_errmsg(g.db));
drhad1ca9a2013-11-23 04:16:58 +0000309 }
310 sqlite3_free(zSql);
311}
312
313/* Prepare an SQL statement */
314void speedtest1_prepare(const char *zFormat, ...){
315 va_list ap;
316 char *zSql;
317 va_start(ap, zFormat);
318 zSql = sqlite3_vmprintf(zFormat, ap);
319 va_end(ap);
320 if( g.bSqlOnly ){
321 int n = (int)strlen(zSql);
322 while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; }
323 printf("%.*s;\n", n, zSql);
324 }else{
325 int rc;
326 if( g.pStmt ) sqlite3_finalize(g.pStmt);
327 rc = sqlite3_prepare_v2(g.db, zSql, -1, &g.pStmt, 0);
328 if( rc ){
329 fatal_error("SQL error: %s\n", sqlite3_errmsg(g.db));
330 }
331 }
332 sqlite3_free(zSql);
333}
334
335/* Run an SQL statement previously prepared */
336void speedtest1_run(void){
337 int i, n, len;
338 if( g.bSqlOnly ) return;
339 assert( g.pStmt );
340 g.nResult = 0;
341 while( sqlite3_step(g.pStmt)==SQLITE_ROW ){
342 n = sqlite3_column_count(g.pStmt);
343 for(i=0; i<n; i++){
344 const char *z = (const char*)sqlite3_column_text(g.pStmt, i);
345 if( z==0 ) z = "nil";
346 len = (int)strlen(z);
347 if( g.nResult+len<sizeof(g.zResult)-2 ){
348 if( g.nResult>0 ) g.zResult[g.nResult++] = ' ';
349 memcpy(g.zResult + g.nResult, z, len+1);
350 g.nResult += len;
351 }
352 }
353 }
354 if( g.bReprepare ){
355 sqlite3_stmt *pNew;
356 sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0);
357 sqlite3_finalize(g.pStmt);
358 g.pStmt = pNew;
359 }else{
360 sqlite3_reset(g.pStmt);
361 }
362}
363
364/* The sqlite3_trace() callback function */
365static void traceCallback(void *NotUsed, const char *zSql){
366 int n = (int)strlen(zSql);
367 while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ) n--;
368 fprintf(stderr,"%.*s;\n", n, zSql);
369}
370
371/* Substitute random() function that gives the same random
372** sequence on each run, for repeatability. */
373static void randomFunc(
374 sqlite3_context *context,
375 int NotUsed,
376 sqlite3_value **NotUsed2
377){
378 sqlite3_result_int64(context, (sqlite3_int64)speedtest1_random());
379}
380
381/*
382** The main and default testset
383*/
384void testset_main(void){
385 int i; /* Loop counter */
386 int n; /* iteration count */
387 int sz; /* Size of the tables */
388 int maxb; /* Maximum swizzled value */
389 unsigned x1, x2; /* Parameters */
390 int len; /* Length of the zNum[] string */
391 char zNum[2000]; /* A number name */
392
393 sz = n = g.szTest*500;
394 maxb = roundup_allones(sz);
395 speedtest1_begin_test(100, "%d INSERTs into table with no index", n);
396 speedtest1_exec("BEGIN");
397 speedtest1_exec("CREATE TABLE t1(a INTEGER %s, b INTEGER %s, c TEXT %s);",
398 g.zNN, g.zNN, g.zNN);
399 speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2,?3); -- %d times", n);
400 for(i=1; i<=n; i++){
401 x1 = swizzle(i,maxb);
402 speedtest1_numbername(x1, zNum, sizeof(zNum));
403 sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1);
404 sqlite3_bind_int(g.pStmt, 2, i);
405 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC);
406 speedtest1_run();
407 }
408 speedtest1_exec("COMMIT");
409 speedtest1_end_test();
410
411
412 n = sz;
413 speedtest1_begin_test(110, "%d ordered INSERTS with one index/PK", n);
414 speedtest1_exec("BEGIN");
415 speedtest1_exec("CREATE TABLE t2(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
416 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
417 speedtest1_prepare("INSERT INTO t2 VALUES(?1,?2,?3); -- %d times", n);
418 for(i=1; i<=n; i++){
419 x1 = swizzle(i,maxb);
420 speedtest1_numbername(x1, zNum, sizeof(zNum));
421 sqlite3_bind_int(g.pStmt, 1, i);
422 sqlite3_bind_int64(g.pStmt, 2, (sqlite3_int64)x1);
423 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC);
424 speedtest1_run();
425 }
426 speedtest1_exec("COMMIT");
427 speedtest1_end_test();
428
429
430 n = sz;
431 speedtest1_begin_test(120, "%d unordered INSERTS with one index/PK", n);
432 speedtest1_exec("BEGIN");
433 speedtest1_exec("CREATE TABLE t3(a INTEGER %s %s, b INTEGER %s, c TEXT %s) %s",
434 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
435 speedtest1_prepare("INSERT INTO t3 VALUES(?1,?2,?3); -- %d times", n);
436 for(i=1; i<=n; i++){
437 x1 = swizzle(i,maxb);
438 speedtest1_numbername(x1, zNum, sizeof(zNum));
439 sqlite3_bind_int(g.pStmt, 2, i);
440 sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1);
441 sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC);
442 speedtest1_run();
443 }
444 speedtest1_exec("COMMIT");
445 speedtest1_end_test();
446
447
448 n = g.szTest/2;
449 speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n);
450 speedtest1_exec("BEGIN");
451 speedtest1_prepare(
452 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
453 " WHERE b BETWEEN ?1 AND ?2; -- %d times", n
454 );
455 for(i=1; i<=n; i++){
456 x1 = speedtest1_random()%maxb;
457 x2 = speedtest1_random()%10 + sz/5000 + x1;
458 sqlite3_bind_int(g.pStmt, 1, x1);
459 sqlite3_bind_int(g.pStmt, 2, x2);
460 speedtest1_run();
461 }
462 speedtest1_exec("COMMIT");
463 speedtest1_end_test();
464
465
466 n = g.szTest/5;
467 speedtest1_begin_test(140, "%d SELECTS, LIKE, unindexed", n);
468 speedtest1_exec("BEGIN");
469 speedtest1_prepare(
470 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
471 " WHERE c LIKE ?1; -- %d times", n
472 );
473 for(i=1; i<=n; i++){
474 x1 = speedtest1_random()%maxb;
475 zNum[0] = '%';
476 len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2);
477 zNum[len] = '%';
478 zNum[len+1] = 0;
479 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC);
480 speedtest1_run();
481 }
482 speedtest1_exec("COMMIT");
483 speedtest1_end_test();
484
485
486 speedtest1_begin_test(150, "CREATE INDEX five times");
487 speedtest1_exec(
488 "BEGIN;\n"
489 "CREATE UNIQUE INDEX t1b ON t1(b);\n"
490 "CREATE INDEX t1c ON t1(c);\n"
491 "CREATE UNIQUE INDEX t2b ON t2(b);\n"
492 "CREATE INDEX t2c ON t2(c DESC);\n"
493 "CREATE INDEX t3bc ON t3(b,c);\n"
494 "COMMIT;\n"
495 );
496 speedtest1_end_test();
497
498
499 n = sz/5;
500 speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n);
501 speedtest1_exec("BEGIN");
502 speedtest1_prepare(
503 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
504 " WHERE b BETWEEN ?1 AND ?2; -- %d times", n
505 );
506 for(i=1; i<=n; i++){
507 x1 = speedtest1_random()%maxb;
508 x2 = speedtest1_random()%10 + sz/5000 + x1;
509 sqlite3_bind_int(g.pStmt, 1, x1);
510 sqlite3_bind_int(g.pStmt, 2, x2);
511 speedtest1_run();
512 }
513 speedtest1_exec("COMMIT");
514 speedtest1_end_test();
515
516
517 n = sz/5;
518 speedtest1_begin_test(161, "%d SELECTS, numeric BETWEEN, PK", n);
519 speedtest1_exec("BEGIN");
520 speedtest1_prepare(
521 "SELECT count(*), avg(b), sum(length(c)) FROM t2\n"
522 " WHERE a BETWEEN ?1 AND ?2; -- %d times", n
523 );
524 for(i=1; i<=n; i++){
525 x1 = speedtest1_random()%maxb;
526 x2 = speedtest1_random()%10 + sz/5000 + x1;
527 sqlite3_bind_int(g.pStmt, 1, x1);
528 sqlite3_bind_int(g.pStmt, 2, x2);
529 speedtest1_run();
530 }
531 speedtest1_exec("COMMIT");
532 speedtest1_end_test();
533
534
535 n = sz/5;
536 speedtest1_begin_test(170, "%d SELECTS, text BETWEEN, indexed", n);
537 speedtest1_exec("BEGIN");
538 speedtest1_prepare(
539 "SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
540 " WHERE c BETWEEN ?1 AND (?1||'~'); -- %d times", n
541 );
542 for(i=1; i<=n; i++){
543 x1 = swizzle(i, maxb);
544 len = speedtest1_numbername(x1, zNum, sizeof(zNum)-1);
545 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC);
546 speedtest1_run();
547 }
548 speedtest1_exec("COMMIT");
549 speedtest1_end_test();
550
551 n = sz;
552 speedtest1_begin_test(180, "%d INSERTS with three indexes", n);
553 speedtest1_exec("BEGIN");
554 speedtest1_exec(
555 "CREATE TABLE t4(\n"
556 " a INTEGER %s %s,\n"
557 " b INTEGER %s,\n"
558 " c TEXT %s\n"
559 ") %s",
560 g.zNN, g.zPK, g.zNN, g.zNN, g.zWR);
561 speedtest1_exec("CREATE INDEX t4b ON t4(b)");
562 speedtest1_exec("CREATE INDEX t4c ON t4(c)");
563 speedtest1_exec("INSERT INTO t4 SELECT * FROM t1");
564 speedtest1_exec("COMMIT");
565 speedtest1_end_test();
566
567 n = sz;
568 speedtest1_begin_test(190, "DELETE and REFILL one table", n);
569 speedtest1_exec(
570 "DELETE FROM t2;"
571 "INSERT INTO t2 SELECT * FROM t1;"
572 );
573 speedtest1_end_test();
574
575
576 speedtest1_begin_test(200, "VACUUM");
577 speedtest1_exec("VACUUM");
578 speedtest1_end_test();
579
580
581 speedtest1_begin_test(210, "ALTER TABLE ADD COLUMN, and query");
582 speedtest1_exec("ALTER TABLE t2 ADD COLUMN d DEFAULT 123");
583 speedtest1_exec("SELECT sum(d) FROM t2");
584 speedtest1_end_test();
585
586
587 n = sz/5;
588 speedtest1_begin_test(230, "%d UPDATES, numeric BETWEEN, indexed", n);
589 speedtest1_exec("BEGIN");
590 speedtest1_prepare(
591 "UPDATE t2 SET d=b*2 WHERE b 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;
605 speedtest1_begin_test(240, "%d UPDATES of individual rows", n);
606 speedtest1_exec("BEGIN");
607 speedtest1_prepare(
608 "UPDATE t2 SET d=b*3 WHERE a=?1; -- %d times", n
609 );
610 for(i=1; i<=n; i++){
611 x1 = speedtest1_random()%sz + 1;
612 sqlite3_bind_int(g.pStmt, 1, x1);
613 speedtest1_run();
614 }
615 speedtest1_exec("COMMIT");
616 speedtest1_end_test();
617
618 speedtest1_begin_test(250, "One big UPDATE of the whole %d-row table", sz);
619 speedtest1_exec("UPDATE t2 SET d=b*4");
620 speedtest1_end_test();
621
622
623 speedtest1_begin_test(260, "Query added column after filling");
624 speedtest1_exec("SELECT sum(d) FROM t2");
625 speedtest1_end_test();
626
627
628
629 n = sz/5;
630 speedtest1_begin_test(270, "%d DELETEs, numeric BETWEEN, indexed", n);
631 speedtest1_exec("BEGIN");
632 speedtest1_prepare(
633 "DELETE FROM t2 WHERE b BETWEEN ?1 AND ?2; -- %d times", n
634 );
635 for(i=1; i<=n; i++){
636 x1 = speedtest1_random()%maxb + 1;
637 x2 = speedtest1_random()%10 + sz/5000 + x1;
638 sqlite3_bind_int(g.pStmt, 1, x1);
639 sqlite3_bind_int(g.pStmt, 2, x2);
640 speedtest1_run();
641 }
642 speedtest1_exec("COMMIT");
643 speedtest1_end_test();
644
645
646 n = sz;
647 speedtest1_begin_test(280, "%d DELETEs of individual rows", n);
648 speedtest1_exec("BEGIN");
649 speedtest1_prepare(
650 "DELETE FROM t3 WHERE a=?1; -- %d times", n
651 );
652 for(i=1; i<=n; i++){
653 x1 = speedtest1_random()%sz + 1;
654 sqlite3_bind_int(g.pStmt, 1, x1);
655 speedtest1_run();
656 }
657 speedtest1_exec("COMMIT");
658 speedtest1_end_test();
659
660
661 speedtest1_begin_test(290, "Refill two %d-row tables using REPLACE", sz);
drhe19f8322013-11-23 11:45:58 +0000662 speedtest1_exec("REPLACE INTO t2(a,b,c) SELECT a,b,c FROM t1");
663 speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM t1");
drhad1ca9a2013-11-23 04:16:58 +0000664 speedtest1_end_test();
665
666
667 n = sz/5;
668 speedtest1_begin_test(290, "%d four-ways joins", n);
669 speedtest1_exec("BEGIN");
670 speedtest1_prepare(
671 "SELECT t1.c FROM t1, t2, t3, t4\n"
672 " WHERE t4.a BETWEEN ?1 AND ?2\n"
673 " AND t3.a=t4.b\n"
674 " AND t2.a=t3.b\n"
675 " AND t1.c=t2.c"
676 );
677 for(i=1; i<=n; i++){
678 x1 = speedtest1_random()%sz + 1;
679 x2 = speedtest1_random()%10 + x1 + 4;
680 sqlite3_bind_int(g.pStmt, 1, x1);
681 sqlite3_bind_int(g.pStmt, 2, x2);
682 speedtest1_run();
683 }
684 speedtest1_exec("COMMIT");
685 speedtest1_end_test();
686
687
688
689 speedtest1_begin_test(980, "PRAGMA integrity_check");
690 speedtest1_exec("PRAGMA integrity_check");
691 speedtest1_end_test();
692
693
694 speedtest1_begin_test(990, "ANALYZE");
695 speedtest1_exec("ANALYZE");
696 speedtest1_end_test();
697}
698
699/*
700** A testset used for debugging speedtest1 itself.
701*/
702void testset_debug1(void){
703 unsigned i, n;
704 unsigned x1, x2;
705 char zNum[2000]; /* A number name */
706
707 n = g.szTest;
708 for(i=1; i<=n; i++){
709 x1 = swizzle(i, n);
710 x2 = swizzle(x1, n);
711 speedtest1_numbername(x1, zNum, sizeof(zNum));
712 printf("%5d %5d %5d %s\n", i, x1, x2, zNum);
713 }
714}
715
716int main(int argc, char **argv){
717 int doAutovac = 0; /* True for --autovacuum */
718 int cacheSize = 0; /* Desired cache size. 0 means default */
719 int doExclusive = 0; /* True for --exclusive */
720 int nHeap = 0, mnHeap = 0; /* Heap size from --heap */
721 int doIncrvac = 0; /* True for --incrvacuum */
722 const char *zJMode = 0; /* Journal mode */
723 const char *zKey = 0; /* Encryption key */
724 int nLook = 0, szLook = 0; /* --lookaside configuration */
725 int noSync = 0; /* True for --nosync */
726 int pageSize = 0; /* Desired page size. 0 means default */
727 int nPCache = 0, szPCache = 0;/* --pcache configuration */
drh93307e92013-11-24 01:14:14 +0000728 int nScratch = 0, szScratch=0;/* --scratch configuration */
drhad1ca9a2013-11-23 04:16:58 +0000729 int showStats = 0; /* True for --stats */
730 const char *zTSet = "main"; /* Which --testset torun */
731 int doTrace = 0; /* True for --trace */
732 const char *zEncoding = 0; /* --utf16be or --utf16le */
733 const char *zDbName = 0; /* Name of the test database */
734
735 void *pHeap = 0; /* Allocated heap space */
736 void *pLook = 0; /* Allocated lookaside space */
737 void *pPCache = 0; /* Allocated storage for pcache */
drh93307e92013-11-24 01:14:14 +0000738 void *pScratch = 0; /* Allocated storage for scratch */
drhad1ca9a2013-11-23 04:16:58 +0000739 int iCur, iHi; /* Stats values, current and "highwater" */
drhe19f8322013-11-23 11:45:58 +0000740 int i; /* Loop counter */
741 int rc; /* API return code */
drhad1ca9a2013-11-23 04:16:58 +0000742
743 /* Process command-line arguments */
744 g.zWR = "";
745 g.zNN = "";
746 g.zPK = "UNIQUE";
747 g.szTest = 100;
748 for(i=1; i<argc; i++){
749 const char *z = argv[i];
750 if( z[0]=='-' ){
751 do{ z++; }while( z[0]=='-' );
752 if( strcmp(z,"autovacuum")==0 ){
753 doAutovac = 1;
754 }else if( strcmp(z,"cachesize")==0 ){
755 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
756 i++;
drh93307e92013-11-24 01:14:14 +0000757 cacheSize = integerValue(argv[i]);
drhad1ca9a2013-11-23 04:16:58 +0000758 }else if( strcmp(z,"exclusive")==0 ){
759 doExclusive = 1;
760 }else if( strcmp(z,"heap")==0 ){
761 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
drh93307e92013-11-24 01:14:14 +0000762 nHeap = integerValue(argv[i+1]);
763 mnHeap = integerValue(argv[i+2]);
drhad1ca9a2013-11-23 04:16:58 +0000764 i += 2;
765 }else if( strcmp(z,"incrvacuum")==0 ){
766 doIncrvac = 1;
767 }else if( strcmp(z,"journal")==0 ){
768 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
769 zJMode = argv[++i];
770 }else if( strcmp(z,"key")==0 ){
771 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
772 zKey = argv[++i];
773 }else if( strcmp(z,"lookaside")==0 ){
774 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
drh93307e92013-11-24 01:14:14 +0000775 nLook = integerValue(argv[i+1]);
776 szLook = integerValue(argv[i+2]);
drhad1ca9a2013-11-23 04:16:58 +0000777 i += 2;
778 }else if( strcmp(z,"nosync")==0 ){
779 noSync = 1;
780 }else if( strcmp(z,"notnull")==0 ){
781 g.zNN = "NOT NULL";
782 }else if( strcmp(z,"pagesize")==0 ){
783 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
drh93307e92013-11-24 01:14:14 +0000784 pageSize = integerValue(argv[++i]);
drhad1ca9a2013-11-23 04:16:58 +0000785 }else if( strcmp(z,"pcache")==0 ){
786 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
drh93307e92013-11-24 01:14:14 +0000787 nPCache = integerValue(argv[i+1]);
788 szPCache = integerValue(argv[i+2]);
drhad1ca9a2013-11-23 04:16:58 +0000789 i += 2;
790 }else if( strcmp(z,"primarykey")==0 ){
791 g.zPK = "PRIMARY KEY";
792 }else if( strcmp(z,"reprepare")==0 ){
793 g.bReprepare = 1;
drh93307e92013-11-24 01:14:14 +0000794 }else if( strcmp(z,"scratch")==0 ){
795 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
796 nScratch = integerValue(argv[i+1]);
797 szScratch = integerValue(argv[i+2]);
798 i += 2;
drhad1ca9a2013-11-23 04:16:58 +0000799 }else if( strcmp(z,"sqlonly")==0 ){
800 g.bSqlOnly = 1;
801 }else if( strcmp(z,"size")==0 ){
802 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
drh93307e92013-11-24 01:14:14 +0000803 g.szTest = integerValue(argv[++i]);
drhad1ca9a2013-11-23 04:16:58 +0000804 }else if( strcmp(z,"stats")==0 ){
805 showStats = 1;
806 }else if( strcmp(z,"testset")==0 ){
807 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
808 zTSet = argv[++i];
809 }else if( strcmp(z,"trace")==0 ){
810 doTrace = 1;
811 }else if( strcmp(z,"utf16le")==0 ){
812 zEncoding = "utf16le";
813 }else if( strcmp(z,"utf16be")==0 ){
814 zEncoding = "utf16be";
815 }else if( strcmp(z,"without-rowid")==0 ){
816 g.zWR = "WITHOUT ROWID";
817 g.zPK = "PRIMARY KEY";
818 }else if( strcmp(z, "help")==0 || strcmp(z,"?")==0 ){
819 printf(zHelp, argv[0]);
820 exit(0);
821 }else{
822 fatal_error("unknown option: %s\nUse \"%s -?\" for help\n",
823 argv[i], argv[0]);
824 }
825 }else if( zDbName==0 ){
826 zDbName = argv[i];
827 }else{
828 fatal_error("surplus argument: %s\nUse \"%s -?\" for help\n",
829 argv[i], argv[0]);
830 }
831 }
832#if 0
833 if( zDbName==0 ){
834 fatal_error(zHelp, argv[0]);
835 }
836#endif
837 if( nHeap>0 ){
838 pHeap = malloc( nHeap );
839 if( pHeap==0 ) fatal_error("cannot allocate %d-byte heap\n", nHeap);
drhe19f8322013-11-23 11:45:58 +0000840 rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
drh7b65ad32013-11-23 21:29:07 +0000841 if( rc ) fatal_error("heap configuration failed: %d\n", rc);
drhad1ca9a2013-11-23 04:16:58 +0000842 }
843 if( nPCache>0 && szPCache>0 ){
drh93307e92013-11-24 01:14:14 +0000844 pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
845 if( pPCache==0 ) fatal_error("cannot allocate %lld-byte pcache\n",
846 nPCache*(sqlite3_int64)szPCache);
drhe19f8322013-11-23 11:45:58 +0000847 rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
drh7b65ad32013-11-23 21:29:07 +0000848 if( rc ) fatal_error("pcache configuration failed: %d\n", rc);
drhad1ca9a2013-11-23 04:16:58 +0000849 }
drh93307e92013-11-24 01:14:14 +0000850 if( nScratch>0 && szScratch>0 ){
851 pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
852 if( pScratch==0 ) fatal_error("cannot allocate %lld-byte scratch\n",
853 nScratch*(sqlite3_int64)szScratch);
854 rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
855 if( rc ) fatal_error("scratch configuration failed: %d\n", rc);
856 }
drhad1ca9a2013-11-23 04:16:58 +0000857 if( nLook>0 ){
858 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
859 }
860
861 /* Open the database and the input file */
862 if( sqlite3_open(zDbName, &g.db) ){
863 fatal_error("Cannot open database file: %s\n", zDbName);
864 }
865 if( nLook>0 && szLook>0 ){
866 pLook = malloc( nLook*szLook );
drhe19f8322013-11-23 11:45:58 +0000867 rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook,nLook);
drh7b65ad32013-11-23 21:29:07 +0000868 if( rc ) fatal_error("lookaside configuration failed: %d\n", rc);
drhad1ca9a2013-11-23 04:16:58 +0000869 }
870
871 /* Set database connection options */
872 sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0);
873 if( doTrace ) sqlite3_trace(g.db, traceCallback, 0);
874 if( zKey ){
875 speedtest1_exec("PRAGMA key('%s')", zKey);
876 }
877 if( zEncoding ){
878 speedtest1_exec("PRAGMA encoding=%s", zEncoding);
879 }
880 if( doAutovac ){
881 speedtest1_exec("PRAGMA auto_vacuum=FULL");
882 }else if( doIncrvac ){
883 speedtest1_exec("PRAGMA auto_vacuum=INCREMENTAL");
884 }
885 if( pageSize ){
886 speedtest1_exec("PRAGMA page_size=%d", pageSize);
887 }
888 if( cacheSize ){
889 speedtest1_exec("PRAGMA cache_size=%d", cacheSize);
890 }
891 if( noSync ) speedtest1_exec("PRAGMA synchronous=OFF");
892 if( doExclusive ){
893 speedtest1_exec("PRAGMA locking_mode=EXCLUSIVE");
894 }
895 if( zJMode ){
896 speedtest1_exec("PRAGMA journal_mode=%s", zJMode);
897 }
898
899 if( strcmp(zTSet,"main")==0 ){
900 testset_main();
901 }else if( strcmp(zTSet,"debug1")==0 ){
902 testset_debug1();
903 }else{
904 fatal_error("unknown testset: \"%s\"\n", zTSet);
905 }
906 speedtest1_final();
907
908 /* Database connection statistics printed after both prepared statements
909 ** have been finalized */
drh290ea402013-12-01 18:10:01 +0000910#if SQLITE_VERSION_NUMBER>=3007009
drhad1ca9a2013-11-23 04:16:58 +0000911 if( showStats ){
912 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHi, 0);
913 printf("-- Lookaside Slots Used: %d (max %d)\n", iCur,iHi);
914 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHi, 0);
915 printf("-- Successful lookasides: %d\n", iHi);
916 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur,&iHi,0);
917 printf("-- Lookaside size faults: %d\n", iHi);
918 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur,&iHi,0);
919 printf("-- Lookaside OOM faults: %d\n", iHi);
920 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHi, 0);
921 printf("-- Pager Heap Usage: %d bytes\n", iCur);
922 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHi, 1);
923 printf("-- Page cache hits: %d\n", iCur);
924 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHi, 1);
drh2a702db2013-12-02 21:25:40 +0000925 printf("-- Page cache misses: %d\n", iCur);
926#if SQLITE_VERSION_NUMBER>=3007012
drhad1ca9a2013-11-23 04:16:58 +0000927 sqlite3_db_status(g.db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHi, 1);
928 printf("-- Page cache writes: %d\n", iCur);
drh2a702db2013-12-02 21:25:40 +0000929#endif
drhad1ca9a2013-11-23 04:16:58 +0000930 sqlite3_db_status(g.db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHi, 0);
931 printf("-- Schema Heap Usage: %d bytes\n", iCur);
932 sqlite3_db_status(g.db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHi, 0);
933 printf("-- Statement Heap Usage: %d bytes\n", iCur);
934 }
drh290ea402013-12-01 18:10:01 +0000935#endif
drhad1ca9a2013-11-23 04:16:58 +0000936
937 sqlite3_close(g.db);
938
939 /* Global memory usage statistics printed after the database connection
940 ** has closed. Memory usage should be zero at this point. */
941 if( showStats ){
942 sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHi, 0);
943 printf("-- Memory Used (bytes): %d (max %d)\n", iCur,iHi);
drhd79e9c52013-12-02 01:24:05 +0000944#if SQLITE_VERSION_NUMBER>=3007000
drhad1ca9a2013-11-23 04:16:58 +0000945 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHi, 0);
946 printf("-- Outstanding Allocations: %d (max %d)\n", iCur,iHi);
drhd79e9c52013-12-02 01:24:05 +0000947#endif
drhad1ca9a2013-11-23 04:16:58 +0000948 sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHi, 0);
949 printf("-- Pcache Overflow Bytes: %d (max %d)\n", iCur,iHi);
950 sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHi, 0);
951 printf("-- Scratch Overflow Bytes: %d (max %d)\n", iCur,iHi);
952 sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHi, 0);
953 printf("-- Largest Allocation: %d bytes\n",iHi);
954 sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHi, 0);
955 printf("-- Largest Pcache Allocation: %d bytes\n",iHi);
956 sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHi, 0);
957 printf("-- Largest Scratch Allocation: %d bytes\n", iHi);
958 }
959
960 /* Release memory */
961 free( pLook );
962 free( pPCache );
drh93307e92013-11-24 01:14:14 +0000963 free( pScratch );
drhad1ca9a2013-11-23 04:16:58 +0000964 free( pHeap );
965 return 0;
966}