############################################################################### # # stress.eagle -- # # Written by Joe Mistachkin. # Released to the public domain, use at your own risk! # ############################################################################### package require Eagle package require Eagle.Library package require Eagle.Test runTestPrologue ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### runTest {test stress-1.1 {multithreaded stress testing} -setup { set count(0) 1 set count(1) 10 if {[info exists argv] && [llength $argv] > 0} then { parse options [list \ [list null MustHaveIntegerValue -1 -1 -count0 $count(0)] \ [list null MustHaveIntegerValue -1 -1 -count1 $count(1)]] $argv set count(0) $options(-count0,value) set count(1) $options(-count1,value) } ############################################################################# tputs $test_channel [appendArgs \ "---- workloads will repeat " $count(0) " time(s)...\n"] tputs $test_channel [appendArgs \ "---- workloads will have " $count(1) " iteration(s)...\n"] ############################################################################# setupDb [set fileName(1) :memory:] "" "" "" "" "" false srcDb setupDb [set fileName(2) [file join [getDatabaseDirectory] stress.db]] ############################################################################# set workload(1) [list [list srcDb fileName table count] { # # NOTE: Workload #1, CREATE TABLE statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 2} {$index <= $count} {incr index} { sql execute $db [appendArgs \ "CREATE TABLE IF NOT EXISTS t" $index "(x PRIMARY KEY, y, z);"] puts -nonewline stdout 1; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(2) [list [list srcDb fileName table count] { # # NOTE: Workload #2, DROP TABLE statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 2} {$index <= $count} {incr index} { sql execute $db [appendArgs \ "DROP TABLE IF EXISTS t" $index \;] puts -nonewline stdout 2; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(3) [list [list srcDb fileName table count] { # # NOTE: Workload #3, "small" SELECT statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 1} {$index <= $count} {incr index} { sql execute -execute reader $db [appendArgs \ "SELECT x, y FROM " $table " WHERE z = 'small';"] puts -nonewline stdout 3; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(4) [list [list srcDb fileName table count] { # # NOTE: Workload #4, "big" SELECT statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 1} {$index <= $count} {incr index} { sql execute -execute reader $db [appendArgs \ "SELECT x, y FROM " $table " WHERE z = 'big';"] puts -nonewline stdout 4; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(5) [list [list srcDb fileName table count] { # # NOTE: Workload #5, "small" INSERT statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 1} {$index <= $count} {incr index} { sql execute $db [appendArgs \ "INSERT INTO " $table "(x, y, z) VALUES('" \ [format %lX [expr {random()}]] ',' \ [base64 encode [expr {randstr(10000)}]] \ "','small');"] puts -nonewline stdout 5; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(6) [list [list srcDb fileName table count] { # # NOTE: Workload #6, "big" INSERT statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 1} {$index <= $count} {incr index} { sql execute $db [appendArgs \ "INSERT INTO " $table "(x, y, z) VALUES('" \ [format %lX [expr {random()}]] ',' \ [base64 encode [expr {randstr(10000000)}]] \ "','big');"] puts -nonewline stdout 6; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(7) [list [list srcDb fileName table count] { # # NOTE: Workload #7, "small" UPDATE statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 1} {$index <= $count} {incr index} { sql execute $db [appendArgs "UPDATE " $table \ " SET y = '" [base64 encode [expr {randstr(10000)}]] \ "' WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"] puts -nonewline stdout 7; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(8) [list [list srcDb fileName table count] { # # NOTE: Workload #8, "big" UPDATE statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 1} {$index <= $count} {incr index} { sql execute $db [appendArgs "UPDATE " $table \ " SET y = '" [base64 encode [expr {randstr(10000000)}]] \ "' WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"] puts -nonewline stdout 8; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(9) [list [list srcDb fileName table count] { # # NOTE: Workload #9, "small" DELETE statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 1} {$index <= $count} {incr index} { sql execute $db [appendArgs "DELETE FROM " $table \ " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"] puts -nonewline stdout 9; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(10) [list [list srcDb fileName table count] { # # NOTE: Workload #10, "big" DELETE statements. # setupDb $fileName "" "" "" "" "" false if {[catch { for {set index 1} {$index <= $count} {incr index} { sql execute $db [appendArgs "DELETE FROM " $table \ " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"] puts -nonewline stdout A; after [expr {int(rand() * 1000)}] } } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(11) [list [list srcDb fileName table count] { # # NOTE: Workload #11, VACUUM statement. # setupDb $fileName "" "" "" "" "" false if {[catch { sql execute $db "VACUUM;" puts -nonewline stdout B; after [expr {int(rand() * 1000)}] } error]} then { if {[regexp -- {\sno such table: t1\s} $error]} then { puts -nonewline stdout * } else { puts stdout "" puts stdout [appendArgs [info level [info level]] ": " $error] puts stdout "" } } cleanupDb $fileName db false false }] ############################################################################# set workload(12) [list [list srcDb fileName table count] { # # NOTE: Workload #12, backup to in-memory database. # set id [object invoke Interpreter.GetActive NextId] set source [object invoke -flags +NonPublic -objectflags +NoDispose \ Interpreter.GetActive.connections get_Item $srcDb] set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Text; namespace _Dynamic${id} { public static class Test${id} { public static void BackupAndGetData( SQLiteConnection source ) { using (SQLiteConnection destination = new SQLiteConnection( "Data Source=:memory:;")) { destination.Open(); source.BackupDatabase(destination, "main", "main", -1, null, 0); } } ///////////////////////////////////////////////////////////////////// public static void Main() { // do nothing. } } } }] true true true results errors System.Data.SQLite.dll] if {$code eq "Ok"} then { object invoke _Dynamic${id}.Test${id} BackupAndGetData $source } else { error $errors } puts -nonewline stdout C; after [expr {int(rand() * 1000)}] }] ############################################################################# set workload(13) [list [list srcDb fileName table count] { # # NOTE: Workload #13, backup from an in-memory database. # set id [object invoke Interpreter.GetActive NextId] set source [object invoke -flags +NonPublic -objectflags +NoDispose \ Interpreter.GetActive.connections get_Item $srcDb] set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Text; namespace _Dynamic${id} { public static class Test${id} { public static void BackupAndGetData( SQLiteConnection source ) { using (SQLiteConnection destination = new SQLiteConnection( "Data Source=${fileName};")) { destination.Open(); source.BackupDatabase(destination, "main", "main", -1, null, 0); } } ///////////////////////////////////////////////////////////////////// public static void Main() { // do nothing. } } } }] true true true results errors System.Data.SQLite.dll] if {$code eq "Ok"} then { object invoke _Dynamic${id}.Test${id} BackupAndGetData $source } else { error $errors } puts -nonewline stdout D; after [expr {int(rand() * 1000)}] }] } -body { for {set index(0) 0} {$index(0) < $count(0)} {incr index(0)} { sql execute $db "CREATE TABLE IF NOT EXISTS t1(x PRIMARY KEY, y, z);" unset -nocomplain thread foreach index(1) [array names workload] { set thread($index(1)) [object create -alias System.Threading.Thread \ [list apply $workload($index(1)) $srcDb $fileName(2) t1 $count(1)]] } foreach index(1) [array names thread] { $thread($index(1)) Start } foreach index(1) [array names thread] { $thread($index(1)) Join } } puts stdout "" } -cleanup { cleanupDb $fileName(2) cleanupDb $fileName(1) srcDb unset -nocomplain thread index workload srcDb db fileName options count } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result {}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue