1# 2005 November 30 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 test cases focused on the two memory-management APIs, 13# sqlite3_soft_heap_limit() and sqlite3_release_memory(). 14# 15# Prior to version 3.6.2, calling sqlite3_release_memory() or exceeding 16# the configured soft heap limit could cause sqlite to upgrade database 17# locks and flush dirty pages to the file system. As of 3.6.2, this is 18# no longer the case. In version 3.6.2, sqlite3_release_memory() only 19# reclaims clean pages. This test file has been updated accordingly. 20# 21# $Id: malloc5.test,v 1.22 2009/04/11 19:09:54 drh Exp $ 22 23sqlite3_shutdown 24sqlite3_config_pagecache 0 100 25sqlite3_initialize 26autoinstall_test_functions 27 28set testdir [file dirname $argv0] 29source $testdir/tester.tcl 30source $testdir/malloc_common.tcl 31db close 32 33# Only run these tests if memory debugging is turned on. 34# 35if {!$MEMDEBUG} { 36 puts "Skipping malloc5 tests: not compiled with -DSQLITE_MEMDEBUG..." 37 finish_test 38 return 39} 40 41# Skip these tests if OMIT_MEMORY_MANAGEMENT was defined at compile time. 42ifcapable !memorymanage { 43 finish_test 44 return 45} 46 47sqlite3_soft_heap_limit 0 48sqlite3 db test.db 49db eval {PRAGMA cache_size=1} 50 51do_test malloc5-1.1 { 52 # Simplest possible test. Call sqlite3_release_memory when there is exactly 53 # one unused page in a single pager cache. The page cannot be freed, as 54 # it is dirty. So sqlite3_release_memory() returns 0. 55 # 56 execsql { 57 PRAGMA auto_vacuum=OFF; 58 BEGIN; 59 CREATE TABLE abc(a, b, c); 60 } 61 sqlite3_release_memory 62} {0} 63 64do_test malloc5-1.2 { 65 # Test that the transaction started in the above test is still active. 66 # The lock on the database file should not have been upgraded (this was 67 # not the case before version 3.6.2). 68 # 69 sqlite3 db2 test.db 70 execsql {PRAGMA cache_size=2; SELECT * FROM sqlite_master } db2 71} {} 72do_test malloc5-1.3 { 73 # Call [sqlite3_release_memory] when there is exactly one unused page 74 # in the cache belonging to db2. 75 # 76 set ::pgalloc [sqlite3_release_memory] 77} {0} 78 79# The sizes of memory allocations from system malloc() might vary, 80# depending on the memory allocator algorithms used. The following 81# routine is designed to support answers that fall within a range 82# of values while also supplying easy-to-understand "expected" values 83# when errors occur. 84# 85proc value_in_range {target x args} { 86 set v [lindex $args 0] 87 if {$v!=""} { 88 if {$v<$target*$x} {return $v} 89 if {$v>$target/$x} {return $v} 90 } 91 return "number between [expr {int($target*$x)}] and [expr {int($target/$x)}]" 92} 93set mrange 0.98 ;# plus or minus 2% 94 95 96do_test malloc5-1.4 { 97 # Commit the transaction and open a new one. Read 1 page into the cache. 98 # Because the page is not dirty, it is eligible for collection even 99 # before the transaction is concluded. 100 # 101 execsql { 102 COMMIT; 103 BEGIN; 104 SELECT * FROM abc; 105 } 106 value_in_range $::pgalloc $::mrange [sqlite3_release_memory] 107} [value_in_range $::pgalloc $::mrange] 108 109do_test malloc5-1.5 { 110 # Conclude the transaction opened in the previous [do_test] block. This 111 # causes another page (page 1) to become eligible for recycling. 112 # 113 execsql { COMMIT } 114 value_in_range $::pgalloc $::mrange [sqlite3_release_memory] 115} [value_in_range $::pgalloc $::mrange] 116 117do_test malloc5-1.6 { 118 # Manipulate the cache so that it contains two unused pages. One requires 119 # a journal-sync to free, the other does not. 120 db2 close 121 execsql { 122 BEGIN; 123 SELECT * FROM abc; 124 CREATE TABLE def(d, e, f); 125 } 126 value_in_range $::pgalloc $::mrange [sqlite3_release_memory 500] 127} [value_in_range $::pgalloc $::mrange] 128 129do_test malloc5-1.7 { 130 # Database should not be locked this time. 131 sqlite3 db2 test.db 132 catchsql { SELECT * FROM abc } db2 133} {0 {}} 134do_test malloc5-1.8 { 135 # Try to release another block of memory. This will fail as the only 136 # pages currently in the cache are dirty (page 3) or pinned (page 1). 137 db2 close 138 sqlite3_release_memory 500 139} 0 140do_test malloc5-1.8 { 141 # Database is still not locked. 142 # 143 sqlite3 db2 test.db 144 catchsql { SELECT * FROM abc } db2 145} {0 {}} 146do_test malloc5-1.9 { 147 execsql { 148 COMMIT; 149 } 150} {} 151 152do_test malloc5-2.1 { 153 # Put some data in tables abc and def. Both tables are still wholly 154 # contained within their root pages. 155 execsql { 156 INSERT INTO abc VALUES(1, 2, 3); 157 INSERT INTO abc VALUES(4, 5, 6); 158 INSERT INTO def VALUES(7, 8, 9); 159 INSERT INTO def VALUES(10,11,12); 160 } 161} {} 162do_test malloc5-2.2 { 163 # Load the root-page for table def into the cache. Then query table abc. 164 # Halfway through the query call sqlite3_release_memory(). The goal of this 165 # test is to make sure we don't free pages that are in use (specifically, 166 # the root of table abc). 167 sqlite3_release_memory 168 set nRelease 0 169 execsql { 170 BEGIN; 171 SELECT * FROM def; 172 } 173 set data [list] 174 db eval {SELECT * FROM abc} { 175 incr nRelease [sqlite3_release_memory] 176 lappend data $a $b $c 177 } 178 execsql { 179 COMMIT; 180 } 181 list $nRelease $data 182} [list $pgalloc [list 1 2 3 4 5 6]] 183 184do_test malloc5-3.1 { 185 # Simple test to show that if two pagers are opened from within this 186 # thread, memory is freed from both when sqlite3_release_memory() is 187 # called. 188 execsql { 189 BEGIN; 190 SELECT * FROM abc; 191 } 192 execsql { 193 SELECT * FROM sqlite_master; 194 BEGIN; 195 SELECT * FROM def; 196 } db2 197 value_in_range [expr $::pgalloc*2] 0.99 [sqlite3_release_memory] 198} [value_in_range [expr $::pgalloc * 2] 0.99] 199do_test malloc5-3.2 { 200 concat \ 201 [execsql {SELECT * FROM abc; COMMIT}] \ 202 [execsql {SELECT * FROM def; COMMIT} db2] 203} {1 2 3 4 5 6 7 8 9 10 11 12} 204 205db2 close 206puts "Highwater mark: [sqlite3_memory_highwater]" 207 208# The following two test cases each execute a transaction in which 209# 10000 rows are inserted into table abc. The first test case is used 210# to ensure that more than 1MB of dynamic memory is used to perform 211# the transaction. 212# 213# The second test case sets the "soft-heap-limit" to 100,000 bytes (0.1 MB) 214# and tests to see that this limit is not exceeded at any point during 215# transaction execution. 216# 217# Before executing malloc5-4.* we save the value of the current soft heap 218# limit in variable ::soft_limit. The original value is restored after 219# running the tests. 220# 221set ::soft_limit [sqlite3_soft_heap_limit -1] 222execsql {PRAGMA cache_size=2000} 223do_test malloc5-4.1 { 224 execsql {BEGIN;} 225 execsql {DELETE FROM abc;} 226 for {set i 0} {$i < 10000} {incr i} { 227 execsql "INSERT INTO abc VALUES($i, $i, '[string repeat X 100]');" 228 } 229 execsql {COMMIT;} 230 db cache flush 231 sqlite3_release_memory 232 sqlite3_memory_highwater 1 233 execsql {SELECT * FROM abc} 234 set nMaxBytes [sqlite3_memory_highwater 1] 235 puts -nonewline " (Highwater mark: $nMaxBytes) " 236 expr $nMaxBytes > 1000000 237} {1} 238do_test malloc5-4.2 { 239 db eval {PRAGMA cache_size=1} 240 db cache flush 241 sqlite3_release_memory 242 sqlite3_soft_heap_limit 100000 243 sqlite3_memory_highwater 1 244 execsql {SELECT * FROM abc} 245 set nMaxBytes [sqlite3_memory_highwater 1] 246 puts -nonewline " (Highwater mark: $nMaxBytes) " 247 expr $nMaxBytes <= 110000 248} {1} 249do_test malloc5-4.3 { 250 # Check that the content of table abc is at least roughly as expected. 251 execsql { 252 SELECT count(*), sum(a), sum(b) FROM abc; 253 } 254} [list 10000 [expr int(10000.0 * 4999.5)] [expr int(10000.0 * 4999.5)]] 255 256# Restore the soft heap limit. 257sqlite3_soft_heap_limit $::soft_limit 258 259# Test that there are no problems calling sqlite3_release_memory when 260# there are open in-memory databases. 261# 262# At one point these tests would cause a seg-fault. 263# 264do_test malloc5-5.1 { 265 db close 266 sqlite3 db :memory: 267 execsql { 268 BEGIN; 269 CREATE TABLE abc(a, b, c); 270 INSERT INTO abc VALUES('abcdefghi', 1234567890, NULL); 271 INSERT INTO abc SELECT * FROM abc; 272 INSERT INTO abc SELECT * FROM abc; 273 INSERT INTO abc SELECT * FROM abc; 274 INSERT INTO abc SELECT * FROM abc; 275 INSERT INTO abc SELECT * FROM abc; 276 INSERT INTO abc SELECT * FROM abc; 277 INSERT INTO abc SELECT * FROM abc; 278 } 279 sqlite3_release_memory 280} 0 281do_test malloc5-5.2 { 282 sqlite3_soft_heap_limit 5000 283 execsql { 284 COMMIT; 285 PRAGMA temp_store = memory; 286 SELECT * FROM abc ORDER BY a; 287 } 288 expr 1 289} {1} 290sqlite3_soft_heap_limit $::soft_limit 291 292#------------------------------------------------------------------------- 293# The following test cases (malloc5-6.*) test the new global LRU list 294# used to determine the pages to recycle when sqlite3_release_memory is 295# called and there is more than one pager open. 296# 297proc nPage {db} { 298 set bt [btree_from_db $db] 299 array set stats [btree_pager_stats $bt] 300 set stats(page) 301} 302db close 303forcedelete test.db test.db-journal test2.db test2.db-journal 304 305# This block of test-cases (malloc5-6.1.*) prepares two database files 306# for the subsequent tests. 307do_test malloc5-6.1.1 { 308 sqlite3 db test.db 309 execsql { 310 PRAGMA page_size=1024; 311 PRAGMA default_cache_size=2; 312 } 313 execsql { 314 PRAGMA temp_store = memory; 315 BEGIN; 316 CREATE TABLE abc(a PRIMARY KEY, b, c); 317 INSERT INTO abc VALUES(randstr(50,50), randstr(75,75), randstr(100,100)); 318 INSERT INTO abc 319 SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; 320 INSERT INTO abc 321 SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; 322 INSERT INTO abc 323 SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; 324 INSERT INTO abc 325 SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; 326 INSERT INTO abc 327 SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; 328 INSERT INTO abc 329 SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc; 330 COMMIT; 331 } 332 forcecopy test.db test2.db 333 sqlite3 db2 test2.db 334 db2 eval {PRAGMA cache_size=2} 335 list \ 336 [expr ([file size test.db]/1024)>20] [expr ([file size test2.db]/1024)>20] 337} {1 1} 338do_test malloc5-6.1.2 { 339 list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2] 340} {2 2} 341 342do_test malloc5-6.2.1 { 343 execsql {SELECT * FROM abc} db2 344 execsql {SELECT * FROM abc} db 345 expr [nPage db] + [nPage db2] 346} {4} 347 348do_test malloc5-6.2.2 { 349 # If we now try to reclaim some memory, it should come from the db2 cache. 350 sqlite3_release_memory 3000 351 expr [nPage db] + [nPage db2] 352} {4} 353do_test malloc5-6.2.3 { 354 # Access the db2 cache again, so that all the db2 pages have been used 355 # more recently than all the db pages. Then try to reclaim 3000 bytes. 356 # This time, 3 pages should be pulled from the db cache. 357 execsql { SELECT * FROM abc } db2 358 sqlite3_release_memory 3000 359 expr [nPage db] + [nPage db2] 360} {4} 361 362do_test malloc5-6.3.1 { 363 # Now open a transaction and update 2 pages in the db2 cache. Then 364 # do a SELECT on the db cache so that all the db pages are more recently 365 # used than the db2 pages. When we try to free memory, SQLite should 366 # free the non-dirty db2 pages, then the db pages, then finally use 367 # sync() to free up the dirty db2 pages. The only page that cannot be 368 # freed is page1 of db2. Because there is an open transaction, the 369 # btree layer holds a reference to page 1 in the db2 cache. 370 execsql { 371 BEGIN; 372 UPDATE abc SET c = randstr(100,100) 373 WHERE rowid = 1 OR rowid = (SELECT max(rowid) FROM abc); 374 } db2 375 execsql { SELECT * FROM abc } db 376 expr [nPage db] + [nPage db2] 377} {4} 378do_test malloc5-6.3.2 { 379 # Try to release 7700 bytes. This should release all the 380 # non-dirty pages held by db2. 381 sqlite3_release_memory [expr 7*1132] 382 list [nPage db] [nPage db2] 383} {1 3} 384do_test malloc5-6.3.3 { 385 # Try to release another 1000 bytes. This should come fromt the db 386 # cache, since all three pages held by db2 are either in-use or diry. 387 sqlite3_release_memory 1000 388 list [nPage db] [nPage db2] 389} {1 3} 390do_test malloc5-6.3.4 { 391 # Now release 9900 more (about 9 pages worth). This should expunge 392 # the rest of the db cache. But the db2 cache remains intact, because 393 # SQLite tries to avoid calling sync(). 394 if {$::tcl_platform(wordSize)==8} { 395 sqlite3_release_memory 10500 396 } else { 397 sqlite3_release_memory 9900 398 } 399 list [nPage db] [nPage db2] 400} {1 3} 401do_test malloc5-6.3.5 { 402 # But if we are really insistent, SQLite will consent to call sync() 403 # if there is no other option. UPDATE: As of 3.6.2, SQLite will not 404 # call sync() in this scenario. So no further memory can be reclaimed. 405 sqlite3_release_memory 1000 406 list [nPage db] [nPage db2] 407} {1 3} 408do_test malloc5-6.3.6 { 409 # The referenced page (page 1 of the db2 cache) will not be freed no 410 # matter how much memory we ask for: 411 sqlite3_release_memory 31459 412 list [nPage db] [nPage db2] 413} {1 3} 414 415db2 close 416 417sqlite3_soft_heap_limit $::soft_limit 418finish_test 419catch {db close} 420