perf(database): bound the read pool's mapping and cache by measurement
#283 read as "64 MB of mmap and up to 32 MB of page cache per pool", and it is — but on a 50 000-track library neither is what the process's memory is: the RSS of the database mapping is 46 MB whether the bound is 64 MB or 16 MB, because a mapping costs what the working set touches. Quartering it and halving the page cache moved no query either: 1 172 → 1 197 ms for the whole track list, 106 → 124 ms for the album list, 6 → 8 ms for an FTS search, all inside the run-to-run spread. Kept, because a bound that costs nothing measurable is worth having on a phone: five read connections' worth of mapping is 320 MB of address space at 64 MB each against 80 MB here, and #52 was a low-memory kill. Closes #283
This commit is contained in:
1 parent
620151aa41
commit
c9b3048a20
1 file changed
+13
-3
@@ -54,9 +54,19 @@ type DB struct {
|
||||
// form is silently ignored, which is why WAL was never actually on.
|
||||
const (
|
||||
writeDSNParams = "?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)"
|
||||
// The read pool's own page cache and mapping bound, sized by
|
||||
// measurement rather than by appetite (#283). On a 50 000-track
|
||||
// library, halving the cache and quartering the mapping moved no
|
||||
// query — 1 172 → 1 197 ms for the whole track list, 106 → 124 ms
|
||||
// for the album list, 6 → 8 ms for an FTS search, all inside the
|
||||
// run-to-run spread — and the RSS of the database mapping was 46 MB
|
||||
// under both settings, because a mapping's cost is what the working
|
||||
// set touches, not the bound. The bound is what matters on a
|
||||
// phone, where five connections' worth of address space is the
|
||||
// thing the low-memory killer reads (cf. #52).
|
||||
readDSNParams = "?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)" +
|
||||
"&_pragma=query_only(true)&_pragma=synchronous(NORMAL)" +
|
||||
"&_pragma=cache_size(-8000)&_pragma=mmap_size(67108864)"
|
||||
"&_pragma=cache_size(-2000)&_pragma=mmap_size(16777216)"
|
||||
// readPoolConns bounds concurrent read connections. A handful is
|
||||
// plenty for interactive search + art/lookup fan-out and keeps WAL
|
||||
// reader overhead small.
|
||||
@@ -354,8 +364,8 @@ func applyPRAGMAs(ctx context.Context, db *sql.DB) error {
|
||||
pragmas := []string{
|
||||
"PRAGMA foreign_keys = ON",
|
||||
"PRAGMA synchronous = NORMAL",
|
||||
"PRAGMA cache_size = -8000",
|
||||
"PRAGMA mmap_size = 67108864",
|
||||
"PRAGMA cache_size = -2000",
|
||||
"PRAGMA mmap_size = 16777216",
|
||||
}
|
||||
|
||||
for _, pragma := range pragmas {
|
||||
|
||||
Reference in new issue
Block a user