github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/pools/query_pools.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package pools 22 23 import ( 24 "github.com/m3db/m3/src/dbnode/encoding" 25 "github.com/m3db/m3/src/dbnode/encoding/m3tsz" 26 "github.com/m3db/m3/src/dbnode/namespace" 27 "github.com/m3db/m3/src/dbnode/x/xio" 28 "github.com/m3db/m3/src/dbnode/x/xpool" 29 xconfig "github.com/m3db/m3/src/x/config" 30 "github.com/m3db/m3/src/x/ident" 31 "github.com/m3db/m3/src/x/instrument" 32 "github.com/m3db/m3/src/x/pool" 33 "github.com/m3db/m3/src/x/serialize" 34 xsync "github.com/m3db/m3/src/x/sync" 35 36 "github.com/uber-go/tally" 37 ) 38 39 const ( 40 // TODO: add capabilities to get this from configs 41 defaultReplicas = 3 42 defaultSeriesIteratorPoolSize = 2 << 12 // ~8k 43 defaultCheckedBytesWrapperPoolSize = 2 << 12 // ~8k 44 defaultPoolableConcurrentQueries = 64 45 defaultPoolableSeriesPerQuery = 4096 46 ) 47 48 var ( 49 defaultSeriesIteratorsPoolBuckets = []pool.Bucket{ 50 { 51 Capacity: defaultPoolableSeriesPerQuery, 52 Count: defaultPoolableConcurrentQueries, 53 }, 54 } 55 defaultSeriesIDBytesPoolBuckets = []pool.Bucket{ 56 { 57 Capacity: 256, // Can pool IDs up to 256 in size with this bucket. 58 Count: defaultPoolableSeriesPerQuery, 59 }, 60 { 61 Capacity: 1024, // Can pool IDs up to 1024 in size with this bucket. 62 Count: defaultPoolableSeriesPerQuery, 63 }, 64 } 65 ) 66 67 // BuildWorkerPools builds a worker pool 68 func BuildWorkerPools( 69 instrumentOptions instrument.Options, 70 readPoolPolicy, writePoolPolicy xconfig.WorkerPoolPolicy, 71 scope tally.Scope, 72 ) (xsync.PooledWorkerPool, xsync.PooledWorkerPool, error) { 73 opts, readPoolSize := readPoolPolicy.Options() 74 opts = opts.SetInstrumentOptions(instrumentOptions. 75 SetMetricsScope(scope.SubScope("read-worker-pool"))) 76 readWorkerPool, err := xsync.NewPooledWorkerPool(readPoolSize, opts) 77 if err != nil { 78 return nil, nil, err 79 } 80 81 readWorkerPool.Init() 82 opts, writePoolSize := writePoolPolicy.Options() 83 opts = opts.SetInstrumentOptions(instrumentOptions. 84 SetMetricsScope(scope.SubScope("write-worker-pool"))) 85 writeWorkerPool, err := xsync.NewPooledWorkerPool(writePoolSize, opts) 86 if err != nil { 87 return nil, nil, err 88 } 89 90 writeWorkerPool.Init() 91 return readWorkerPool, writeWorkerPool, nil 92 } 93 94 type sessionPools struct { 95 multiReaderIteratorArray encoding.MultiReaderIteratorArrayPool 96 multiReaderIterator encoding.MultiReaderIteratorPool 97 seriesIterator encoding.SeriesIteratorPool 98 checkedBytesWrapper xpool.CheckedBytesWrapperPool 99 id ident.Pool 100 tagEncoder serialize.TagEncoderPool 101 tagDecoder serialize.TagDecoderPool 102 } 103 104 func (s sessionPools) MultiReaderIteratorArray() encoding.MultiReaderIteratorArrayPool { 105 return s.multiReaderIteratorArray 106 } 107 108 func (s sessionPools) MultiReaderIterator() encoding.MultiReaderIteratorPool { 109 return s.multiReaderIterator 110 } 111 112 func (s sessionPools) SeriesIterator() encoding.SeriesIteratorPool { 113 return s.seriesIterator 114 } 115 116 func (s sessionPools) CheckedBytesWrapper() xpool.CheckedBytesWrapperPool { 117 return s.checkedBytesWrapper 118 } 119 120 func (s sessionPools) ID() ident.Pool { 121 return s.id 122 } 123 124 func (s sessionPools) TagEncoder() serialize.TagEncoderPool { 125 return s.tagEncoder 126 } 127 128 func (s sessionPools) TagDecoder() serialize.TagDecoderPool { 129 return s.tagDecoder 130 } 131 132 // BuildIteratorPoolsOptions is a set of build iterator pools. 133 type BuildIteratorPoolsOptions struct { 134 Replicas int 135 SeriesIteratorPoolSize int 136 SeriesIteratorsPoolBuckets []pool.Bucket 137 SeriesIDBytesPoolBuckets []pool.Bucket 138 CheckedBytesWrapperPoolSize int 139 } 140 141 // ReplicasOrDefault returns the replicas or default. 142 func (o BuildIteratorPoolsOptions) ReplicasOrDefault() int { 143 if o.Replicas <= 0 { 144 return defaultReplicas 145 } 146 return o.Replicas 147 } 148 149 // SeriesIteratorPoolSizeOrDefault returns the replicas or default. 150 func (o BuildIteratorPoolsOptions) SeriesIteratorPoolSizeOrDefault() int { 151 if o.SeriesIteratorPoolSize <= 0 { 152 return defaultSeriesIteratorPoolSize 153 } 154 return o.SeriesIteratorPoolSize 155 } 156 157 // CheckedBytesWrapperPoolSizeOrDefault returns the checked bytes 158 // wrapper pool size or default. 159 func (o BuildIteratorPoolsOptions) CheckedBytesWrapperPoolSizeOrDefault() int { 160 if o.CheckedBytesWrapperPoolSize <= 0 { 161 return defaultCheckedBytesWrapperPoolSize 162 } 163 return o.CheckedBytesWrapperPoolSize 164 } 165 166 // SeriesIteratorsPoolBucketsOrDefault returns the series iterator pool 167 // buckets or defaults. 168 func (o BuildIteratorPoolsOptions) SeriesIteratorsPoolBucketsOrDefault() []pool.Bucket { 169 if len(o.SeriesIteratorsPoolBuckets) == 0 { 170 return defaultSeriesIteratorsPoolBuckets 171 } 172 return o.SeriesIteratorsPoolBuckets 173 } 174 175 // SeriesIDBytesPoolBucketsOrDefault returns the bytes pool buckets or defaults. 176 func (o BuildIteratorPoolsOptions) SeriesIDBytesPoolBucketsOrDefault() []pool.Bucket { 177 if len(o.SeriesIDBytesPoolBuckets) == 0 { 178 return defaultSeriesIDBytesPoolBuckets 179 } 180 return o.SeriesIDBytesPoolBuckets 181 } 182 183 // BuildIteratorPools build iterator pools if they are unavailable from 184 // m3db (e.g. if running standalone query) 185 func BuildIteratorPools( 186 encodingOpts encoding.Options, 187 opts BuildIteratorPoolsOptions, 188 ) encoding.IteratorPools { 189 // TODO: add instrumentation options to these pools 190 pools := sessionPools{} 191 192 defaultPerSeriesIteratorsBuckets := opts.SeriesIteratorsPoolBucketsOrDefault() 193 194 pools.multiReaderIteratorArray = encoding.NewMultiReaderIteratorArrayPool(defaultPerSeriesIteratorsBuckets) 195 pools.multiReaderIteratorArray.Init() 196 197 defaultPerSeriesPoolOpts := pool.NewObjectPoolOptions(). 198 SetSize(opts.SeriesIteratorPoolSizeOrDefault()) 199 200 readerIteratorPoolPoolOpts := pool.NewObjectPoolOptions(). 201 SetSize(opts.SeriesIteratorPoolSizeOrDefault() * opts.ReplicasOrDefault()) 202 203 readerIteratorPool := encoding.NewReaderIteratorPool(readerIteratorPoolPoolOpts) 204 205 encodingOpts = encodingOpts. 206 SetReaderIteratorPool(readerIteratorPool) 207 208 readerIteratorPool.Init(m3tsz.DefaultReaderIteratorAllocFn(encodingOpts)) 209 210 pools.multiReaderIterator = encoding.NewMultiReaderIteratorPool(defaultPerSeriesPoolOpts) 211 pools.multiReaderIterator.Init( 212 func(r xio.Reader64, s namespace.SchemaDescr) encoding.ReaderIterator { 213 iter := readerIteratorPool.Get() 214 iter.Reset(r, s) 215 return iter 216 }) 217 218 pools.seriesIterator = encoding.NewSeriesIteratorPool(defaultPerSeriesPoolOpts) 219 pools.seriesIterator.Init() 220 221 wrapperPoolOpts := pool.NewObjectPoolOptions(). 222 SetSize(opts.CheckedBytesWrapperPoolSizeOrDefault()) 223 pools.checkedBytesWrapper = xpool.NewCheckedBytesWrapperPool(wrapperPoolOpts) 224 pools.checkedBytesWrapper.Init() 225 226 pools.tagEncoder = serialize.NewTagEncoderPool( 227 serialize.NewTagEncoderOptions(), 228 defaultPerSeriesPoolOpts) 229 pools.tagEncoder.Init() 230 231 tagDecoderCheckBytesWrapperPoolSize := 0 232 tagDecoderOpts := serialize.NewTagDecoderOptions(serialize.TagDecoderOptionsConfig{ 233 // We pass in a preallocated pool so use a zero sized pool in options init. 234 CheckBytesWrapperPoolSize: &tagDecoderCheckBytesWrapperPoolSize, 235 }) 236 tagDecoderOpts = tagDecoderOpts.SetCheckedBytesWrapperPool(pools.checkedBytesWrapper) 237 238 pools.tagDecoder = serialize.NewTagDecoderPool(tagDecoderOpts, defaultPerSeriesPoolOpts) 239 pools.tagDecoder.Init() 240 241 bytesPool := pool.NewCheckedBytesPool(opts.SeriesIDBytesPoolBucketsOrDefault(), 242 nil, func(sizes []pool.Bucket) pool.BytesPool { 243 return pool.NewBytesPool(sizes, nil) 244 }) 245 bytesPool.Init() 246 247 pools.id = ident.NewPool(bytesPool, ident.PoolOptions{ 248 IDPoolOptions: defaultPerSeriesPoolOpts, 249 TagsPoolOptions: defaultPerSeriesPoolOpts, 250 TagsIteratorPoolOptions: defaultPerSeriesPoolOpts, 251 }) 252 253 return pools 254 }