Dear experts,

In my application performance is of critical importance.  I've chosen to
preallocate a large contiguous block of memory for the page cache.

I make use of the following function to configure the page cache:
sqlite3_config(SQLITE_CONFIG_PAGECACHE, void*, int sz, int N);

The documentation for this function says the following:
*This option specifies a static memory buffer that SQLite can use for the
database page cache with the default page cache implementation. There are
three arguments to this option: A pointer to 8-byte aligned memory, the
size of each page buffer (sz), and the number of pages (N). The sz argument
should be the size of the largest database page (a power of two between 512
and 32768) plus a little extra for each page header. The page header size
is 20 to 40 bytes depending on the host architecture. It is harmless, apart
from the wasted memory, to make sz a little too large.*

Now, first of all, with my default database block size of 1024, the 20 to
40 bytes documented for the cache header size is wrong.  On the Linux and
HP-UX Itanium systems where I've tested this with SQLite 3.7.8, the cache
header size was 248 bytes.  This could be seen in the output from
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE) which returned a value of
about 1272 bytes.  (1272 - 1024 = 248).  This means the page cache header
size is already 25% of the size of the actual data block, or put
differently, 20% of the preallocated cache buffer is 'lost' to the header
component.  With a cache buffer of 5 GB, this means a total of 1 GB for the
header meta data only.

SQLite is a little quirky in the way that even though I may allocate a
block of 1 GB of memory for the page cache, if I specify a too small cache
block size (sz value) in the call to
sqlite3_config(SQLITE_CONFIG_PAGECACHE, void*, int sz, int N), then the
cache page allocation from the preallocated buffer will fail and that
memory won't be used for the cache at all, instead it falls back to the
default allocator and simply allocates additional memory for the cache.
The preallocated memory block is totally wasted.

Now since my application performs a high number of transactions, the page
cache grows to several GB of memory.  Since memory is also a finite
resource, I tried to limit the cache block size to the minimum required.
When I first tried it with the documented 20 - 40 additional bytes for the
header, it failed.  However, using the 248 header bytes that resulted from
the output of sqlite_status(SQLITE_STATUS_PAGECACHE_SIZE), it worked fine.
That was with SQLite version 3.7.8.

Now my dilemma is that it seems the page cache block header size was
increased from 3.7.8 to 3.7.10.  With 3.7.10
sqlite_status(SQLITE_STATUS_PAGECACHE_SIZE) now returns 1312 bytes,
indicating a page cache header size of 288 bytes.  This means that once
again my application is not using the preallocated buffer at all, but is
allocating cache with malloc() and is running out of memory.  So I have to
change the header size constant, recompile and redeploy the application.

In order to avoid this scenario in future with future releases of SQLite,
is there a way to determine the page cache header size within the code,
keeping in mind that the page cache is configured using sqlite3_config() *
before* the call to sqlite3_initialize()?

Any advice on handling this problem would be much appreciated.

Best regards,
Jaco
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to