1# 2008 June 18 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# 12# This file contains tests of the memory allocation subsystem 13# 14 15set testdir [file dirname $argv0] 16source $testdir/tester.tcl 17sqlite3_reset_auto_extension 18 19# This test assumes that no page-cache or scratch buffers are installed 20# by default when a new database connection is opened. As a result, it 21# will not work with the "memsubsys1" permutation. 22# 23if {[permutation] == "memsubsys1"} { 24 finish_test 25 return 26} 27 28# This procedure constructs a new database in test.db. It fills 29# this database with many small records (enough to force multiple 30# rebalance operations in the btree-layer and to require a large 31# page cache), verifies correct results, then returns. 32# 33proc build_test_db {testname pragmas} { 34 catch {db close} 35 file delete -force test.db test.db-journal 36 sqlite3 db test.db 37 sqlite3_db_config_lookaside db 0 0 0 38 db eval $pragmas 39 db eval { 40 CREATE TABLE t1(x, y); 41 CREATE TABLE t2(a, b); 42 CREATE INDEX i1 ON t1(x,y); 43 INSERT INTO t1 VALUES(1, 100); 44 INSERT INTO t1 VALUES(2, 200); 45 } 46 for {set i 2} {$i<5000} {incr i $i} { 47 db eval {INSERT INTO t2 SELECT * FROM t1} 48 db eval {INSERT INTO t1 SELECT a+$i, a+b*100 FROM t2} 49 db eval {DELETE FROM t2} 50 } 51 do_test $testname.1 { 52 db eval {SELECT count(*) FROM t1} 53 } 8192 54 integrity_check $testname.2 55} 56 57# Reset all of the highwater marks. 58# 59proc reset_highwater_marks {} { 60 sqlite3_status SQLITE_STATUS_MEMORY_USED 1 61 sqlite3_status SQLITE_STATUS_MALLOC_SIZE 1 62 sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1 63 sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 1 64 sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 1 65 sqlite3_status SQLITE_STATUS_SCRATCH_USED 1 66 sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 1 67 sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 1 68 sqlite3_status SQLITE_STATUS_PARSER_STACK 1 69} 70 71set xtra_size 256 72 73# Test 1: Both PAGECACHE and SCRATCH are shut down. 74# 75db close 76sqlite3_shutdown 77sqlite3_config_lookaside 0 0 78sqlite3_initialize 79reset_highwater_marks 80build_test_db memsubsys1-1 {PRAGMA page_size=1024} 81do_test memsubsys1-1.3 { 82 set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] 83} 0 84do_test memsubsys1-1.4 { 85 set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 86} 0 87set max_pagecache [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] 88#show_memstats 89 90# Test 2: Activate PAGECACHE with 20 pages 91# 92db close 93sqlite3_shutdown 94sqlite3_config_pagecache [expr 1024+$xtra_size] 20 95sqlite3_initialize 96reset_highwater_marks 97build_test_db memsubsys1-2 {PRAGMA page_size=1024} 98#show_memstats 99do_test memsubsys1-2.3 { 100 set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] 101} [expr $AUTOVACUUM*1024] 102do_test memsubsys1-2.4 { 103 set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] 104} 20 105do_test memsubsys1-2.5 { 106 set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 107} 0 108 109# Test 3: Activate PAGECACHE with 20 pages but use the wrong page size 110# so that PAGECACHE is not used. 111# 112db close 113sqlite3_shutdown 114sqlite3_config_pagecache [expr 512+$xtra_size] 20 115sqlite3_initialize 116reset_highwater_marks 117build_test_db memsubsys1-3.1 {PRAGMA page_size=1024} 118#show_memstats 119do_test memsubsys1-3.1.3 { 120 set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] 121} 0 122do_test memsubsys1-3.1.4 { 123 set overflow [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] 124} $max_pagecache 125do_test memsubsys1-3.1.5 { 126 set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 127} 0 128db close 129sqlite3_shutdown 130sqlite3_config_pagecache [expr 2048+$xtra_size] 20 131sqlite3_initialize 132reset_highwater_marks 133build_test_db memsubsys1-3.2 {PRAGMA page_size=2048} 134#show_memstats 135do_test memsubsys1-3.2.3 { 136 db eval {PRAGMA page_size} 137} 2048 138do_test memsubsys1-3.2.4 { 139 set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] 140} 20 141do_test memsubsys1-3.2.5 { 142 set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 143} 0 144 145# Test 4: Activate both PAGECACHE and SCRATCH. 146# 147db close 148sqlite3_shutdown 149sqlite3_config_pagecache [expr 1024+$xtra_size] 50 150sqlite3_config_scratch 6000 2 151sqlite3_initialize 152reset_highwater_marks 153build_test_db memsubsys1-4 {PRAGMA page_size=1024} 154#show_memstats 155do_test memsubsys1-4.3 { 156 set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] 157 expr {$pg_used>=45 && $pg_used<=50} 158} 1 159do_test memsubsys1-4.4 { 160 set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] 161} 0 162do_test memsubsys1-4.5 { 163 set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2] 164 expr {$maxreq<7000} 165} 1 166do_test memsubsys1-4.6 { 167 set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 168} 1 169 170# Test 5: Activate both PAGECACHE and SCRATCH. But make the page size 171# such that the SCRATCH allocations are too small. 172# 173db close 174sqlite3_shutdown 175sqlite3_config_pagecache [expr 4096+$xtra_size] 24 176sqlite3_config_scratch 6000 2 177sqlite3_initialize 178reset_highwater_marks 179build_test_db memsubsys1-5 {PRAGMA page_size=4096} 180#show_memstats 181do_test memsubsys1-5.3 { 182 set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] 183} 24 184do_test memsubsys1-5.4 { 185 set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2] 186 expr {$maxreq>4096} 187} 1 188do_test memsubsys1-5.5 { 189 set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 190} 0 191do_test memsubsys1-5.6 { 192 set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2] 193 expr {$s_ovfl>6000} 194} 1 195 196# Test 6: Activate both PAGECACHE and SCRATCH with a 4k page size. 197# Make it so that SCRATCH is large enough 198# 199db close 200sqlite3_shutdown 201sqlite3_config_pagecache [expr 4096+$xtra_size] 24 202sqlite3_config_scratch 25300 1 203sqlite3_initialize 204reset_highwater_marks 205build_test_db memsubsys1-6 {PRAGMA page_size=4096} 206#show_memstats 207do_test memsubsys1-6.3 { 208 set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] 209} 24 210#do_test memsubsys1-6.4 { 211# set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2] 212# expr {$maxreq>4096 && $maxreq<=(4096+$xtra_size)} 213#} 1 214do_test memsubsys1-6.5 { 215 set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 216} 1 217do_test memsubsys1-6.6 { 218 set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2] 219} 0 220 221# Test 7: Activate both PAGECACHE and SCRATCH with a 4k page size. 222# Set cache_size small so that no PAGECACHE overflow occurs. Verify 223# that maximum allocation size is small. 224# 225db close 226sqlite3_shutdown 227sqlite3_config_pagecache [expr 4096+$xtra_size] 24 228sqlite3_config_scratch 25300 1 229sqlite3_initialize 230reset_highwater_marks 231build_test_db memsubsys1-7 { 232 PRAGMA page_size=4096; 233 PRAGMA cache_size=10; 234 PRAGMA temp_store=memory; 235} 236#show_memstats 237do_test memsubsys1-7.3 { 238 set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2] 239 expr {$pg_used<24} 240} 1 241do_test memsubsys1-7.4 { 242 set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] 243} 0 244do_test memsubsys1-7.5 { 245 set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2] 246 expr {$maxreq<4100} 247} 1 248do_test memsubsys1-7.6 { 249 set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 250} 1 251do_test memsubsys1-7.7 { 252 set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2] 253} 0 254 255# Test 8: Disable PAGECACHE. Make available SCRATCH zero. Verify that 256# the SCRATCH overflow logic works. 257# 258db close 259sqlite3_shutdown 260sqlite3_config_pagecache 0 0 261sqlite3_config_scratch 25000 0 262sqlite3_initialize 263reset_highwater_marks 264do_test memsubsys1-8.1 { 265 set pg_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2] 266} 0 267do_test memsubsys1-8.2 { 268 set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2] 269} 0 270do_test memsubsys1-8.3 { 271 sqlite3 db :memory: 272 db eval { 273 CREATE TABLE t1(x); 274 INSERT INTO t1 VALUES(zeroblob(400)); 275 INSERT INTO t1 VALUES(zeroblob(400)); 276 INSERT INTO t1 SELECT * FROM t1; 277 INSERT INTO t1 SELECT * FROM t1; 278 INSERT INTO t1 SELECT * FROM t1; 279 } 280 expr {[lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]>0} 281} 1 282db close 283sqlite3_shutdown 284sqlite3_config_memstatus 0 285sqlite3_initialize 286do_test memsubsys1-8.4 { 287 sqlite3 db :memory: 288 db eval { 289 CREATE TABLE t1(x); 290 INSERT INTO t1 VALUES(zeroblob(400)); 291 INSERT INTO t1 VALUES(zeroblob(400)); 292 INSERT INTO t1 SELECT * FROM t1; 293 INSERT INTO t1 SELECT * FROM t1; 294 INSERT INTO t1 SELECT * FROM t1; 295 SELECT rowid FROM t1; 296 } 297} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} 298 299 300db close 301sqlite3_shutdown 302sqlite3_config_memstatus 1 303sqlite3_config_pagecache 0 0 304sqlite3_config_scratch 0 0 305sqlite3_config_lookaside 100 500 306sqlite3_initialize 307autoinstall_test_functions 308finish_test 309