-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[core] Update SQLite schema with WAL journal mode and normal sync #5796
Conversation
@friedbunny, thanks for your PR! By analyzing the annotation information on this pull request, we identified @jfirebaugh, @kkaefer and @brunoabinader to be potential reviewers |
When I experimented with WAL dbs, I never saw any sort of data loss. Even if it happens, we're writing a cache, so if we lose a couple of records, it's not a big deal.
Our current layer is implemented so that it deletes the cache and starts over if the DB file is unreadable. |
Considering that the cached tiles and the offline tiles share the same database, wouldn't this delete as well any offline tiles the user has previously downloaded, not just cached ones? |
This is a good point and is a shortcoming of our combined ambient+offline approach. If the risk of data loss is not meaningfully increased by WAL+Normal, then this won’t be any more of a problem than it already is. It’s also worth noting that Core Data switched to WAL for its backing SQLite database in iOS 7 and OS X 10.9 in 2013, so this is a well-tested configuration on Apple systems. The test failures on CI look legit — I’ll investigate updating them for this PR. |
@friedbunny, thanks for your PR! By analyzing this pull request, we identified @jfirebaugh to be potential reviewers. FB: this was me testing @mention-bot. |
Test failures were because |
Couple notes based on reviewing this, some discussed offline:
|
Many of the examples here mention WAL as a potential aggravator. There are some circumstances where WAL is an improvement (e.g., out of order writes), though.
I haven’t seen slower performance in any circumstance (read or write) so far, but yeah, we should test the ambient caching use case more throughly.
I’d prefer to go whole-hog and use WAL, which seems like it should be the best option for us, but I haven’t tested
There’s no general ticket related to database performance AFAIK. This pull request offers a fairly significant performance increase for everyone, but there’s no particular impetus other than that. Do we need more than GitHub’s “offline” + “performance” tags? |
This sounds good to me.
This is due to #3886. |
Cool! On iOS we’re feeling good about getting this in v3.4.0 and would like to merge this week. This will affect other platforms, so it’s important that we get sign-off from the Android and Qt folks. Any concerns about switching to WAL, @tmpsantos @brunoabinader @zugaldia @tobrun? |
Is it possible at all to have some sort of baseline test for speed so we can attach numbers to this? |
There is one corner case that we need to keep in mind which is this only works with write access to the cache, so if you have a read-only offline database on a read-only partition, it won't work. That said, . This is a fairly easy change to revert in a custom build if we ever need to address this corner case. |
Thanks everybody, sounds like we’re good to go. I’m going to rebase this, let the tests pass, and then merge today. |
2cf843d
to
0cf9e54
Compare
Offers 2×-4× performance, depending on device vintage.
0cf9e54
to
c034ba4
Compare
This pull request changes our offline/ambient cache database schema to use write-ahead logging and normal sync, which greatly increases the speed that resources can be written and read.
Journal modes
SQLite offers several journal modes — we were using the default,
DELETE
, which continuously writes a “rollback journal” that is then deleted at the end of the transaction. This mode offers good data safety and is atomic, but is subsequently somewhat slow.Write-head logging (
WAL
) is a different type of journaling that offers better performance but marginally reduced data safety. WAL effectively writes to a separate cache and periodically flushes back to the main database.The SQLite docs go into great detail about the pros and cons of WAL, so I won’t rehash them here.
Synchronous modes
SQLite also offers several modes of write synchronization.
FULL
is the default (which we were using) and is quite safe, but slow.NORMAL
syncs less often (but still at “critical moments”) and is faster, but comes with a “non-zero” chance of data loss.NORMAL
is the suggested mode to be used in conjunction with WAL and is what this PR uses.NORMAL
only offers a minimal performance increase, so far as I could tell.Performance tests with offline resources
Bottom-line: WAL offers 2× to 5× performance for us on iOS, depending on device vintage. Speeds appear to scale linearly — two rounds of tests were done with ~1000 resources and ~6000 resources. Initial writes/downloads were on my home internet connection, which was not saturated.
DELETE
+FULL
WAL
+NORMAL
The iPhone 5 appeared to be severely CPU-bound and was pegged at 100%.
Availability
WAL was first supported in SQLite 3.7.0, which is available from iOS 5 and Android API 11 — so it should be available everywhere.
Unknowns
/cc @mapbox/gl