]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Re-implement the core of the multi-threaded sorter tests in sort4.test using C. Run...
authordan <dan@noemail.net>
Tue, 6 May 2014 15:38:07 +0000 (15:38 +0000)
committerdan <dan@noemail.net>
Tue, 6 May 2014 15:38:07 +0000 (15:38 +0000)
FossilOrigin-Name: 208b2b04d4d282bec4424ea7160a123ba549d118

manifest
manifest.uuid
src/test1.c
test/permutations.test
test/sort4.test

index ac504dddc61825ce0012e98c15e003b90d9f4686..e5ca2b242a51a23f5555f59cb97b6548cce58439 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\stest\sfile\ssort4.test,\scontaining\sbrute\sforce\stests\sfor\sthe\smulti-theaded\ssorter.
-D 2014-05-05T20:03:50.967
+C Re-implement\sthe\score\sof\sthe\smulti-threaded\ssorter\stests\sin\ssort4.test\susing\sC.\sRun\seach\stest\sin\ssort4.test\sten\stimes,\sor\srepeat\sall\stests\sfor\s300\sseconds\sas\spart\sof\sthe\s"multithread"\spermutation\stest.
+D 2014-05-06T15:38:07.762
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in ad0921c4b2780d01868cf69b419a4f102308d125
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -228,7 +228,7 @@ F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
 F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd
-F src/test1.c bd88cc00bff2f15279d808e84501f06148c144f9
+F src/test1.c a0e59104fec5626bb1d1bd746157f43e85245e4b
 F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
 F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
 F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
@@ -741,7 +741,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
-F test/permutations.test 465bc22a873ced74a6d1dedc0dde5da424be6e6a
+F test/permutations.test 33e7e239ba494fdb30e2f4ffc64c508b145ff42f
 F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0
 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@@ -824,7 +824,7 @@ F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
 F test/sort.test 688468cef8c9a66fcc1d54235de8e4deac745690
 F test/sort2.test c5e25eb674689e291d06b5209fe8d337ae0ec010
 F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2
-F test/sort4.test a29761a7d05f194e516e91a03d38f8194ac9849d
+F test/sort4.test 5cce4601abc9b1b63ac25d087723b257710577bb
 F test/sortfault.test 1a12b6e27d475f50658a8164aaa34f0080a86b36
 F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
 F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
@@ -1171,7 +1171,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 2d2edfe58db101d42a96772b856e6e55b401aab6
-R a3f7784643670968322db5c49315411c
+P 9cc364c42cc64ab7b55b5c55e303fb63a456cf00
+R 3ed4f872bc36ee2cfbd000cc3f4dde43
 U dan
-Z cca87b3c456f151b38b423a6310da351
+Z 5684026d864e64d9d77cb71d6b4cd16b
index f77d0e5e6fee9abe60e0e8464525d119b21021fc..4e0ab1c048b05960a46f84eeb7620bf055703b59 100644 (file)
@@ -1 +1 @@
-9cc364c42cc64ab7b55b5c55e303fb63a456cf00
\ No newline at end of file
+208b2b04d4d282bec4424ea7160a123ba549d118
\ No newline at end of file
index 403a7fafa7c0323554092d38243f7fa7b4a7f8b2..2d0efb949e81aec52991b442a34c0d61ce9b317a 100644 (file)
@@ -6370,6 +6370,79 @@ static int sorter_test_fakeheap(
   return TCL_OK;
 }
 
+/*
+**     sorter_test_sort4_helper DB SQL1 NSTEP SQL2
+**
+** Compile SQL statement $SQL1 and step it $NSTEP times. For each row, 
+** check that the leftmost and rightmost columns returned are both integers,
+** and that both contain the same value.
+**
+** Then execute statement $SQL2. Check that the statement returns the same
+** set of integers in the same order as in the previous step (using $SQL1).
+*/
+static int sorter_test_sort4_helper(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  const char *zSql1;
+  const char *zSql2;
+  int nStep; 
+  int iStep; 
+  int iCksum1 = 0; 
+  int iCksum2 = 0; 
+  int rc;
+  int iB;
+  sqlite3 *db;
+  sqlite3_stmt *pStmt;
+  
+  if( objc!=5 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "DB SQL1 NSTEP SQL2");
+    return TCL_ERROR;
+  }
+
+  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+  zSql1 = Tcl_GetString(objv[2]);
+  if( Tcl_GetIntFromObj(interp, objv[3], &nStep) ) return TCL_ERROR;
+  zSql2 = Tcl_GetString(objv[4]);
+
+  rc = sqlite3_prepare_v2(db, zSql1, -1, &pStmt, 0);
+  if( rc!=SQLITE_OK ) goto sql_error;
+
+  iB = sqlite3_column_count(pStmt)-1;
+  for(iStep=0; iStep<nStep && SQLITE_ROW==sqlite3_step(pStmt); iStep++){
+    int a = sqlite3_column_int(pStmt, 0);
+    if( a!=sqlite3_column_int(pStmt, iB) ){
+      Tcl_AppendResult(interp, "data error: (a!=b)", 0);
+      return TCL_ERROR;
+    }
+
+    iCksum1 += (iCksum1 << 3) + a;
+  }
+  rc = sqlite3_finalize(pStmt);
+  if( rc!=SQLITE_OK ) goto sql_error;
+
+  rc = sqlite3_prepare_v2(db, zSql2, -1, &pStmt, 0);
+  if( rc!=SQLITE_OK ) goto sql_error;
+  for(iStep=0; SQLITE_ROW==sqlite3_step(pStmt); iStep++){
+    int a = sqlite3_column_int(pStmt, 0);
+    iCksum2 += (iCksum2 << 3) + a;
+  }
+  rc = sqlite3_finalize(pStmt);
+  if( rc!=SQLITE_OK ) goto sql_error;
+
+  if( iCksum1!=iCksum2 ){
+    Tcl_AppendResult(interp, "checksum mismatch", 0);
+    return TCL_ERROR;
+  }
+
+  return TCL_OK;
+ sql_error:
+  Tcl_AppendResult(interp, "sql error: ", sqlite3_errmsg(db), 0);
+  return TCL_ERROR;
+}
+
 
 /*
 ** Register commands with the TCL interpreter.
@@ -6604,6 +6677,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
 #endif
      { "load_static_extension", tclLoadStaticExtensionCmd },
      { "sorter_test_fakeheap", sorter_test_fakeheap },
+     { "sorter_test_sort4_helper", sorter_test_sort4_helper },
   };
   static int bitmask_size = sizeof(Bitmask)*8;
   int i;
index 3cf4aa80b2ba9d61228acf048e5ac3d144f7336a..e114caf207eae6514f11d78d8b196e8dfe68fa63 100644 (file)
@@ -469,7 +469,7 @@ test_suite "multithread" -description {
 } -files {
   delete.test   delete2.test  insert.test  rollback.test  select1.test
   select2.test  trans.test    update.test  vacuum.test    types.test
-  types2.test   types3.test
+  types2.test   types3.test   sort4.test
 } -shutdown {
   catch {db close}
   sqlite3_shutdown
index 3fb335cb2fb533ac72c852749eb50cb03dcf5cee..7bee0aad2790ea5a9c59646d5c05192b076b2f7f 100644 (file)
@@ -18,16 +18,39 @@ set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 set testprefix sort4
 
+# Configure the sorter to use 3 background threads.
 catch { db close }
 sqlite3_shutdown
 sqlite3_config_worker_threads 3
 sqlite3_initialize
 reset_db
 
+# Minimum number of seconds to run for. If the value is 0, each test
+# is run exactly once. Otherwise, tests are repeated until the timeout
+# expires.
+set SORT4TIMEOUT 0
+if {[permutation] == "multithread"} { set SORT4TIMEOUT 300 }
+
 #--------------------------------------------------------------------
 # Set up a table "t1" containing $nRow rows. Each row contains also
-# contains blob fields that total to at least $nPayload bytes of 
-# content.
+# contains blob fields that collectively contain at least $nPayload 
+# bytes of content. The table schema is as follows:
+#
+#   CREATE TABLE t1(a INTEGER, <extra-columns>, b INTEGER);
+#
+# For each row, the values of columns "a" and "b" are set to the same
+# pseudo-randomly selected integer. The "extra-columns", of which there
+# are at most eight, are named c0, c1, c2 etc. Column c0 contains a 4
+# byte string. Column c1 an 8 byte string. Field c2 16 bytes, and so on.
+#
+# This table is intended to be used for testing queries of the form: 
+#
+#   SELECT a, <cols>, b FROM t1 ORDER BY a;
+#
+# The test code checks that rows are returned in order, and that the 
+# values of "a" and "b" are the same for each row (the idea being that
+# if field "b" at the end of the sorter record has not been corrupted, 
+# the rest of the record is probably Ok as well).
 #
 proc populate_table {nRow nPayload} {
   set nCol 0
@@ -57,8 +80,7 @@ proc populate_table {nRow nPayload} {
 
 # Helper for [do_sorter_test]
 #
-proc sorter_test {nRow nRead {nPayload 100} {cache_size 10}} {
-  db eval "PRAGMA cache_size = $cache_size"
+proc sorter_test {nRow nRead nPayload} {
   set res [list]
 
   set nLoad [expr ($nRow > $nRead) ? $nRead : $nRow]
@@ -72,22 +94,25 @@ proc sorter_test {nRow nRead {nPayload 100} {cache_size 10}} {
     if {$nPayload & $mask} { lappend cols $col }
   }
 
-  set n 0
-  db eval "SELECT a, [join $cols ,], b FROM t1 WHERE rowid<=$nRow ORDER BY a" {
-    if {$a!=$b} { error "a!=b (a=$a b=$b)" }
-    lappend res $a
-    incr n
-    if {$n==$nLoad} break
-  }
-
-
-  set sql {SELECT a FROM t1 WHERE rowid<=$nRow ORDER BY a LIMIT $nRead}
-  if {$res != [db eval $sql]} {
-    puts $res
-    puts [db eval {SELECT a FROM t1 WHERE rowid<=$nLoad ORDER BY a}]
-    error "data no good"
-  }
-
+  # Create two SELECT statements. Statement $sql1 uses the sorter to sort
+  # $nRow records of a bit over $nPayload bytes each read from the "t1"
+  # table created by [populate_table] proc above. Rows are sorted in order
+  # of the integer field in each "t1" record.
+  #
+  # The second SQL statement sorts the same set of rows as the first, but
+  # uses a LIMIT clause, causing SQLite to use a temp table instead of the
+  # sorter for sorting.
+  #
+  set sql1 "SELECT a, [join $cols ,], b FROM t1 WHERE rowid<=$nRow ORDER BY a"
+  set sql2 "SELECT a FROM t1 WHERE rowid<=$nRow ORDER BY a LIMIT $nRead"
+
+  # Pass the two SQL statements to a helper command written in C. This
+  # command steps statement $sql1 $nRead times and compares the integer
+  # values in the rows returned with the results of executing $sql2. If
+  # the comparison fails (indicating some bug in the sorter), a Tcl
+  # exception is thrown.
+  #
+  sorter_test_sort4_helper db $sql1 $nRead $sql2
   set {} {} 
 }
 
@@ -119,22 +144,41 @@ proc do_sorter_test {tn args} {
     set a($s) $val
   }
 
-  for {set i 0} {$i < $a(-repeats)} {incr i} {
-    set cmd [list sorter_test $a(-rows) $a(-read) $a(-payload) $a(-cachesize)]
-    do_test $tn.$i $cmd {}
-  }
+  db eval "PRAGMA cache_size = $a(-cachesize)"
+
+  do_test $tn [subst -nocommands {
+    for {set i 0} {[set i] < $a(-repeats)} {incr i} {
+      sorter_test $a(-rows) $a(-read) $a(-payload)
+    }
+  }] {}
+}
+
+proc clock_seconds {} {
+  db one {SELECT strftime('%s')}
 }
 
+#-------------------------------------------------------------------------
+# Begin tests here.
+
+# Create a test database.
 do_test 1 {
   execsql "PRAGMA page_size = 4096"
   populate_table 100000 500
 } {}
 
-do_sorter_test 2 -repeats 10 -rows 1000   -read 100
-do_sorter_test 3 -repeats 10 -rows 100000 -read 1000
-do_sorter_test 4 -repeats 10 -rows 100000 -read 1000 -payload 500
-do_sorter_test 5 -repeats 10 -rows 100000 -read 100000 -payload 8
-do_sorter_test 6 -repeats 10 -rows 100000 -read 10 -payload 8
+set iTimeLimit [expr [clock_seconds] + $SORT4TIMEOUT]
+
+for {set tn 2} {1} {incr tn} {
+  do_sorter_test $tn.2 -repeats 10 -rows 1000   -read 100
+  do_sorter_test $tn.3 -repeats 10 -rows 100000 -read 1000
+  do_sorter_test $tn.4 -repeats 10 -rows 100000 -read 1000 -payload 500
+  do_sorter_test $tn.5 -repeats 10 -rows 100000 -read 100000 -payload 8
+  do_sorter_test $tn.6 -repeats 10 -rows 100000 -read 10 -payload 8
+
+  set iNow [clock_seconds]
+  if {$iNow>=$iTimeLimit} break
+  do_test "$testprefix-([expr $iTimeLimit-$iNow] seconds remain)" {} {}
+}
 
 catch { db close }
 sqlite3_shutdown
@@ -142,4 +186,3 @@ sqlite3_config_worker_threads 0
 sqlite3_initialize
 finish_test
 
-