diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-21 00:42:34 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-21 00:42:34 +0000 |
commit | 8ada10f0861a51b508b1c804b899f547b0132457 (patch) | |
tree | 69ce9765f6d266e20e82428f0b1b12c6dfaceded /sql | |
parent | e68fafe04d29810cebe8d25554863b0cae4c1356 (diff) | |
download | chromium_src-8ada10f0861a51b508b1c804b899f547b0132457.zip chromium_src-8ada10f0861a51b508b1c804b899f547b0132457.tar.gz chromium_src-8ada10f0861a51b508b1c804b899f547b0132457.tar.bz2 |
[sql] Rewrite Connection::Preload() in terms of file reading.
r204860 rewrote sqlite3_preload() to read the file without placing the
data in the SQLite cache to improve memory footprint. No reports of
performance degradation ensued.
This CL rewrites Connection::Preload() to use the SQLite file handle to
read the data, and backs out the preload-cache.patch from third_party/sqlite/.
BUG=243949
Review URL: https://codereview.chromium.org/116443004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@242225 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sql')
-rw-r--r-- | sql/connection.cc | 56 | ||||
-rw-r--r-- | sql/connection.h | 22 |
2 files changed, 51 insertions, 27 deletions
diff --git a/sql/connection.cc b/sql/connection.cc index 0caa9ed..bfea605 100644 --- a/sql/connection.cc +++ b/sql/connection.cc @@ -125,6 +125,22 @@ void InitializeSqlite() { sqlite3_initialize(); } +// Helper to get the sqlite3_file* associated with the "main" database. +int GetSqlite3File(sqlite3* db, sqlite3_file** file) { + *file = NULL; + int rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_FILE_POINTER, file); + if (rc != SQLITE_OK) + return rc; + + // TODO(shess): NULL in file->pMethods has been observed on android_dbg + // content_unittests, even though it should not be possible. + // http://crbug.com/329982 + if (!*file || !(*file)->pMethods) + return SQLITE_ERROR; + + return rc; +} + } // namespace namespace sql { @@ -302,20 +318,33 @@ void Connection::Preload() { return; } - // A statement must be open for the preload command to work. If the meta - // table doesn't exist, it probably means this is a new database and there - // is nothing to preload (so it's OK we do nothing). - if (!DoesTableExist("meta")) + // Use local settings if provided, otherwise use documented defaults. The + // actual results could be fetching via PRAGMA calls. + const int page_size = page_size_ ? page_size_ : 1024; + sqlite3_int64 preload_size = page_size * (cache_size_ ? cache_size_ : 2000); + if (preload_size < 1) return; - Statement dummy(GetUniqueStatement("SELECT * FROM meta")); - if (!dummy.Step()) + + sqlite3_file* file = NULL; + int rc = GetSqlite3File(db_, &file); + if (rc != SQLITE_OK) return; -#if !defined(USE_SYSTEM_SQLITE) - // This function is only defined in Chromium's version of sqlite. - // Do not call it when using system sqlite. - sqlite3_preload(db_); -#endif + sqlite3_int64 file_size = 0; + rc = file->pMethods->xFileSize(file, &file_size); + if (rc != SQLITE_OK) + return; + + // Don't preload more than the file contains. + if (preload_size > file_size) + preload_size = file_size; + + scoped_ptr<char[]> buf(new char[page_size]); + for (sqlite3_int64 pos = 0; pos < file_size; pos += page_size) { + rc = file->pMethods->xRead(file, buf.get(), page_size, pos); + if (rc != SQLITE_OK) + return; + } } void Connection::TrimMemory(bool aggressively) { @@ -429,13 +458,10 @@ bool Connection::Raze() { // the get-go? if (rc == SQLITE_NOTADB || rc == SQLITE_IOERR_SHORT_READ) { sqlite3_file* file = NULL; - rc = sqlite3_file_control(db_, "main", SQLITE_FCNTL_FILE_POINTER, &file); + rc = GetSqlite3File(db_, &file); if (rc != SQLITE_OK) { DLOG(FATAL) << "Failure getting file handle."; return false; - } else if (!file) { - DLOG(FATAL) << "File handle is empty."; - return false; } rc = file->pMethods->xTruncate(file, 0); diff --git a/sql/connection.h b/sql/connection.h index 54c3f8b..5f11e44 100644 --- a/sql/connection.h +++ b/sql/connection.h @@ -187,19 +187,17 @@ class SQL_EXPORT Connection { // an uninitialized or already-closed database. void Close(); - // Pre-loads the first <cache-size> pages into the cache from the file. - // If you expect to soon use a substantial portion of the database, this - // is much more efficient than allowing the pages to be populated organically - // since there is no per-page hard drive seeking. If the file is larger than - // the cache, the last part that doesn't fit in the cache will be brought in - // organically. + // Reads the first <cache-size>*<page-size> bytes of the file to prime the + // filesystem cache. This can be more efficient than faulting pages + // individually. Since this involves blocking I/O, it should only be used if + // the caller will immediately read a substantial amount of data from the + // database. // - // This function assumes your class is using a meta table on the current - // database, as it openes a transaction on the meta table to force the - // database to be initialized. You should feel free to initialize the meta - // table after calling preload since the meta table will already be in the - // database if it exists, and if it doesn't exist, the database won't - // generally exist either. + // TODO(shess): Design a set of histograms or an experiment to inform this + // decision. Preloading should almost always improve later performance + // numbers for this database simply because it pulls operations forward, but + // if the data isn't actually used soon then preloading just slows down + // everything else. void Preload(); // Try to trim the cache memory used by the database. If |aggressively| is |