99 "encoding/json"
1010 "fmt"
1111 "math"
12+ "math/rand"
1213 "slices"
1314 "sync"
1415 "time"
@@ -60,6 +61,18 @@ const (
6061 // levelDBByteOverhead is the number of bytes of constant overhead that
6162 // should be added to a batch size per operation.
6263 levelDBByteOverhead = 8
64+
65+ // minCompactionL0Trigger is the minimum value for CompactionL0Trigger.
66+ minCompactionL0Trigger = 3
67+
68+ // maxCompactionL0Trigger is the maximum value for CompactionL0Trigger.
69+ maxCompactionL0Trigger = 7
70+
71+ // minCompactionTableSize is the minimum value for CompactionTableSize.
72+ minCompactionTableSize = 2 * opt .MiB
73+
74+ // maxCompactionTableSize is the maximum value for CompactionTableSize.
75+ maxCompactionTableSize = 4 * opt .MiB
6376)
6477
6578var (
@@ -98,40 +111,40 @@ type config struct {
98111 // BlockSize is the minimum uncompressed size in bytes of each 'sorted table'
99112 // block.
100113 //
101- // The default value is 4KiB .
114+ // The default value is [opt.DefaultBlockSize] .
102115 BlockSize int `json:"blockSize"`
103116 // CompactionExpandLimitFactor limits compaction size after expanded.
104117 // This will be multiplied by table size limit at compaction target level.
105118 //
106- // The default value is 25 .
119+ // The default value is [opt.DefaultCompactionExpandLimitFactor] .
107120 CompactionExpandLimitFactor int `json:"compactionExpandLimitFactor"`
108121 // CompactionGPOverlapsFactor limits overlaps in grandparent (Level + 2)
109122 // that a single 'sorted table' generates. This will be multiplied by
110123 // table size limit at grandparent level.
111124 //
112- // The default value is 10 .
125+ // The default value is [opt.DefaultCompactionGPOverlapsFactor] .
113126 CompactionGPOverlapsFactor int `json:"compactionGPOverlapsFactor"`
114127 // CompactionL0Trigger defines number of 'sorted table' at level-0 that will
115128 // trigger compaction.
116129 //
117- // The default value is 4 .
130+ // The default value is a random value between [minCompactionL0Trigger] and [maxCompactionL0Trigger] .
118131 CompactionL0Trigger int `json:"compactionL0Trigger"`
119132 // CompactionSourceLimitFactor limits compaction source size. This doesn't apply to
120133 // level-0.
121134 // This will be multiplied by table size limit at compaction target level.
122135 //
123- // The default value is 1 .
136+ // The default value is [opt.DefaultCompactionSourceLimitFactor] .
124137 CompactionSourceLimitFactor int `json:"compactionSourceLimitFactor"`
125138 // CompactionTableSize limits size of 'sorted table' that compaction generates.
126139 // The limits for each level will be calculated as:
127140 // CompactionTableSize * (CompactionTableSizeMultiplier ^ Level)
128141 // The multiplier for each level can also fine-tuned using CompactionTableSizeMultiplierPerLevel.
129142 //
130- // The default value is 2MiB .
143+ // The default value is a random value between [minCompactionTableSize] and [maxCompactionTableSize] .
131144 CompactionTableSize int `json:"compactionTableSize"`
132145 // CompactionTableSizeMultiplier defines multiplier for CompactionTableSize.
133146 //
134- // The default value is 1 .
147+ // The default value is [opt.DefaultCompactionTableSizeMultiplier] .
135148 CompactionTableSizeMultiplier float64 `json:"compactionTableSizeMultiplier"`
136149 // CompactionTableSizeMultiplierPerLevel defines per-level multiplier for
137150 // CompactionTableSize.
@@ -145,11 +158,11 @@ type config struct {
145158 // The multiplier for each level can also fine-tuned using
146159 // CompactionTotalSizeMultiplierPerLevel.
147160 //
148- // The default value is 10MiB .
161+ // The default value is [opt.DefaultCompactionTotalSize] .
149162 CompactionTotalSize int `json:"compactionTotalSize"`
150163 // CompactionTotalSizeMultiplier defines multiplier for CompactionTotalSize.
151164 //
152- // The default value is 10 .
165+ // The default value is [opt.DefaultCompactionTotalSizeMultiplier] .
153166 CompactionTotalSizeMultiplier float64 `json:"compactionTotalSizeMultiplier"`
154167 // DisableSeeksCompaction allows disabling 'seeks triggered compaction'.
155168 // The purpose of 'seeks triggered compaction' is to optimize database so
@@ -185,6 +198,21 @@ type config struct {
185198 MetricUpdateFrequency time.Duration `json:"metricUpdateFrequency"`
186199}
187200
201+ // randomizeCompactionParams sets compaction parameters in cfg to random values
202+ // to spread out compaction behavior across different nodes.
203+ func randomizeCompactionParams (cfg * config ) {
204+ r := rand .New (rand .NewSource (time .Now ().UnixNano ())) // #nosec G404 -- non-crypto randomness is fine here
205+
206+ // generate random defaults for CompactionL0Trigger
207+ compactionL0Trigger := r .Intn (maxCompactionL0Trigger - minCompactionL0Trigger + 1 ) + minCompactionL0Trigger
208+
209+ // generate random defaults for CompactionTableSize
210+ compactionTableSize := (r .Intn (maxCompactionTableSize - minCompactionTableSize + 1 ) + minCompactionTableSize )
211+
212+ cfg .CompactionL0Trigger = compactionL0Trigger
213+ cfg .CompactionTableSize = compactionTableSize
214+ }
215+
188216// New returns a wrapped LevelDB object.
189217func New (file string , configBytes []byte , log logging.Logger , reg prometheus.Registerer ) (database.Database , error ) {
190218 parsedConfig := config {
@@ -196,6 +224,9 @@ func New(file string, configBytes []byte, log logging.Logger, reg prometheus.Reg
196224 MaxManifestFileSize : DefaultMaxManifestFileSize ,
197225 MetricUpdateFrequency : DefaultMetricUpdateFrequency ,
198226 }
227+
228+ randomizeCompactionParams (& parsedConfig )
229+
199230 if len (configBytes ) > 0 {
200231 if err := json .Unmarshal (configBytes , & parsedConfig ); err != nil {
201232 return nil , fmt .Errorf ("%w: %w" , ErrInvalidConfig , err )
0 commit comments