<title>Memory-Mapped I/O</title>
<tcl>hd_keywords {mmap} {memory-mapped I/O}</tcl>

<h1 align="center">Memory-Mapped I/O</h1>

<p>The default mechanism by which SQLite accesses and updates database disk
files is the xRead() and xWrite() methods of the
[sqlite3_io_methods] VFS object.  These methods are typically implemented as
"read()" and "write()" system calls which cause the operating system
to copy disk content between the kernel buffer cache and user space.</p>

<p>Beginning with [version 3.7.17], SQLite has the option of 
accessing disk content directly using memory-mapped I/O and the new
xFetch() and xUnfetch() methods on [sqlite3_io_methods].</p>

<p>There are advantages and disadvantages to using memory-mapped I/O.
Advantages include:</p>

<ol>
<li><p>Many operations, especially I/O intensive operations, can be much
    faster since content does need to be copied between kernel space
    and user space.  In some cases, performance can nearly double.</p>

<li><p>The SQLite library may need less RAM since it shares pages with
    the operating-system page cache and does not always need its own copy of
    working pages.</p>
</ol>

<p>But there are also disadvantages:</p>

<ol>
<li><p>A stray pointer or buffer overflow in the application program
    might change the content of mapped memory, potentially corrupting the
    database file.  Bugs in application program that overwrite memory
    assigned to the SQLite library could, in theory, also cause corruption
    in read/write mode, but that would require that the overwrite
    be followed by a call to xWrite() and in practice the buggy application
    usually errors out or crashes before that point.  With memory-mapped
    I/O, the database corruption occurs immediately and is thus more of a
    risk.</p>

<li><p>An I/O error on a memory-mapped file cannot be caught and dealt with by
    SQLite.  Instead, the I/O error causes a signal which, if not caught
    by the application, results in a program crash.</p>

<li><p>The operating system must have a unified buffer cache in order for
    the memory-mapped I/O extension to work correctly, especially in
    situations where two processes are accessing the same database
    file and one process is using memory-mapped I/O while the other
    is not.  Not all operating systems have a unified buffer cache.
    In some operating systems that claim to have a unified buffer cache,
    the implementation is buggy and can lead to corrupt databases.</p>

<li><p>Performance does not always increase with memory-mapped I/O.  In fact,
    it is possible to construct test cases where performance is reduced
    by the use of memory-mapped I/O, though this is hard to do.</p>
</ol>

<p>Because of the potential disadvantages, memory-mapped I/O is turned
off by default.  To active memory-mapped I/O, use the [mmap_size pragma]
and set the mmap_size to some large number, usually 256MB or larger, depending
on how much address space your application can spare.  The rest is
automatic.  The [PRAGMA mmap_size] statement will be a silent no-op on
systems that do not support memory-mapped I/O.</p>

<h2>How Memory-Mapped I/O Works</h2>

<p>To read a page of database content using the legacy xRead() method,
SQLite first allocates a page-size chunk of heap memory then invokes
the xRead() method which causes the database page content to be copied
into the newly allocated heap memory.  This involves (at a minimum)
a copy of the entire page.</p>

<p>But if SQLite wants to access a page of the databse file and
memory mapped I/O is enabled, it first calls the xFetch() method.
The xFetch() method asks the operating system to return a pointer to
the requested page, if possible.  If the requested page has been or
can be mapped into the application address space, then xFetch returns
a pointer to that page for SQLite to use without having to copy anything.
Skipping the copy step is what makes memory mapped I/O faster.</p>

<p>SQLite does not assume that the xFetch() method will work.  If
a call to xFetch() returns a NULL pointer (indicating that the requested
page is not currently mapped into the applications address space) then
SQLite silently falls back to using xRead().  An error is only reported
if xRead() also fails.</p>

<p>When updating the database file, SQLite always makes a copy of the
page content into heap memory before modifying the page.  This is necessary
since the changes are not suppose to be visible to other processes until
after the transaction commits and so the changes must occur in private memory.
After all needed changes are completed, xWrite() is used to move the content
back into the database file.  The current xWrite() implementions for both
unix and windows check to see if section of the file being written is 
mapped into the applications address space, and if it is the write operation
is implemented using memcpy() rather than invoking a "write()" system call,
but that is just an implementation detail.  A memory copy occurs either way.
So the use of memory mapped I/O does not significantly change the performance
of database changes.  Memory mapped I/O is mostly a benefit for queries.</p>

<h2>Configuring Memory-Mapped I/O</h2>

<p>The "mmap_size" is the maximum number of bytes of the database file that
SQLite will try to map into the process address space at one time.  The
mmap_size applies separately to each database file, so the total amount
of process address space that could potentially be used is the mmap_size
times the number of open database files.</p>

<p>To activate memory-mapped I/O, an application an set the mmap_size to some
large value.  For example:</p>

<blockquote><pre>
PRAGMA mmap_size=268435456;
</pre></blockquote>

<p>To disable memory-mapped I/O, simply set the mmap_size to zero:</p>

<blockquote><pre>
PRAGMA mmap_size=0;
</pre></blockquote>

<p>If mmap_size is set to N then all current implementations map the first
N bytes of the database file and use legacy xRead() calls for any content
beyond N bytes.  If the database file is smaller then N bytes, then the entire
file is mapped.  In the future, new OS interfaces could, in theory, map
regions of the file other than the first N bytes, but no such 
implementation currently exists.</p>

<p>The mmap_size is set separately for each database file using the
"[PRAGMA mmap_size]" statement.  The usual default mmap_size is zero,
meaning that memory mapped I/O is disabled by default.  However, the
default mmap_size can be increased either at compile-time using
the [SQLITE_DEFAULT_MMAP_SIZE] macro or at start-time using the
[sqlite3_config]([SQLITE_CONFIG_MMAP_SIZE],...) interface.</p>

<p>SQLite also maintains a hard upper bound on the mmap_size.  Attempts
to increase the mmap_size above this hard upper bound (using
[PRAGMA mmap_size]) will automatically cap the mmap_size at the hard
upper bound.  If the hard upper bound is zero, then memory mapped I/O
is impossible.  The hard upper bound can be set at compile-time using
the [SQLITE_MAX_MMAP_SIZE] macro.  If [SQLITE_MAX_MMAP_SIZE] is set to
zero, then the code used to implement memory mapped I/O is omitted from
the build.  The hard upper bound is automatically set to zero on certain
platforms (ex: OpenBSD) where memory mapped I/O does not work due to the
lack of a unified buffer cache.</p>

<p>If the hard upper bound on mmap_size is non-zero at compilation time,
it may still be reduced or zeroed at start-time using the
[sqlite3_config]([SQLITE_CONFIG_MMAP_SIZE],X,Y) interface.  The X and
Y parameters must both be 64-bit signed integers. The X parameter
is the default mmap_size of the process and the Y is the new hard upper bound.
The hard upper bound cannot be increased above its compile-time setting
using [SQLITE_CONFIG_MMAP_SIZE] but it can be reduced or zeroed.</p>
