diff --git a/lib/db/lowlevel.go b/lib/db/lowlevel.go index eda38af66..d079ad109 100644 --- a/lib/db/lowlevel.go +++ b/lib/db/lowlevel.go @@ -8,6 +8,7 @@ package db import ( "os" + "strconv" "strings" "sync" "sync/atomic" @@ -23,7 +24,10 @@ import ( const ( dbMaxOpenFiles = 100 dbWriteBuffer = 16 << 20 - dbFlushBatch = dbWriteBuffer / 4 // Some leeway for any leveldb in-memory optimizations +) + +var ( + dbFlushBatch = debugEnvValue("WriteBuffer", dbWriteBuffer) / 4 // Some leeway for any leveldb in-memory optimizations ) // Lowlevel is the lowest level database interface. It has a very simple @@ -47,8 +51,32 @@ type Lowlevel struct { // the database is erased and created from scratch. func Open(location string) (*Lowlevel, error) { opts := &opt.Options{ - OpenFilesCacheCapacity: dbMaxOpenFiles, - WriteBuffer: dbWriteBuffer, + BlockCacheCapacity: debugEnvValue("BlockCacheCapacity", 0), + BlockCacheEvictRemoved: debugEnvValue("BlockCacheEvictRemoved", 0) != 0, + BlockRestartInterval: debugEnvValue("BlockRestartInterval", 0), + BlockSize: debugEnvValue("BlockSize", 0), + CompactionExpandLimitFactor: debugEnvValue("CompactionExpandLimitFactor", 0), + CompactionGPOverlapsFactor: debugEnvValue("CompactionGPOverlapsFactor", 0), + CompactionL0Trigger: debugEnvValue("CompactionL0Trigger", 0), + CompactionSourceLimitFactor: debugEnvValue("CompactionSourceLimitFactor", 0), + CompactionTableSize: debugEnvValue("CompactionTableSize", 0), + CompactionTableSizeMultiplier: float64(debugEnvValue("CompactionTableSizeMultiplier", 0)) / 10.0, + CompactionTotalSize: debugEnvValue("CompactionTotalSize", 0), + CompactionTotalSizeMultiplier: float64(debugEnvValue("CompactionTotalSizeMultiplier", 0)) / 10.0, + DisableBufferPool: debugEnvValue("DisableBufferPool", 0) != 0, + DisableBlockCache: debugEnvValue("DisableBlockCache", 0) != 0, + DisableCompactionBackoff: debugEnvValue("DisableCompactionBackoff", 0) != 0, + DisableLargeBatchTransaction: debugEnvValue("DisableLargeBatchTransaction", 0) != 0, + NoSync: debugEnvValue("NoSync", 0) != 0, + NoWriteMerge: debugEnvValue("NoWriteMerge", 0) != 0, + OpenFilesCacheCapacity: debugEnvValue("OpenFilesCacheCapacity", dbMaxOpenFiles), + WriteBuffer: debugEnvValue("WriteBuffer", dbWriteBuffer), + // The write slowdown and pause can be overridden, but even if they + // are not and the compaction trigger is overridden we need to + // adjust so that we don't pause writes for L0 compaction before we + // even *start* L0 compaction... + WriteL0SlowdownTrigger: debugEnvValue("WriteL0SlowdownTrigger", 2*debugEnvValue("CompactionL0Trigger", opt.DefaultCompactionL0Trigger)), + WriteL0PauseTrigger: debugEnvValue("WriteL0SlowdownTrigger", 3*debugEnvValue("CompactionL0Trigger", opt.DefaultCompactionL0Trigger)), } return open(location, opts) } @@ -80,6 +108,12 @@ func open(location string, opts *opt.Options) (*Lowlevel, error) { if err != nil { return nil, errorSuggestion{err, "is another instance of Syncthing running?"} } + + if debugEnvValue("CompactEverything", 0) != 0 { + if err := db.CompactRange(util.Range{}); err != nil { + l.Warnln("Compacting database:", err) + } + } return NewLowlevel(db, location), nil } @@ -304,3 +338,11 @@ func (it *iter) execIfNotClosed(fn func() bool) bool { } return fn() } + +func debugEnvValue(key string, def int) int { + v, err := strconv.ParseInt(os.Getenv("STDEBUG_"+key), 10, 63) + if err != nil { + return def + } + return int(v) +}