github.com/m3db/m3@v1.5.0/src/x/ident/identifier_pool.go (about) 1 // Copyright (c) 2016 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 ident 22 23 import ( 24 "github.com/m3db/m3/src/x/checked" 25 "github.com/m3db/m3/src/x/context" 26 "github.com/m3db/m3/src/x/pool" 27 ) 28 29 const ( 30 defaultCapacityOptions = 16 31 defaultMaxCapacityOptions = 32 32 ) 33 34 // PoolOptions is a set of pooling options. 35 type PoolOptions struct { 36 IDPoolOptions pool.ObjectPoolOptions 37 TagsPoolOptions pool.ObjectPoolOptions 38 TagsCapacity int 39 TagsMaxCapacity int 40 TagsIteratorPoolOptions pool.ObjectPoolOptions 41 } 42 43 func (o PoolOptions) defaultsIfNotSet() PoolOptions { 44 if o.IDPoolOptions == nil { 45 o.IDPoolOptions = pool.NewObjectPoolOptions() 46 } 47 if o.TagsPoolOptions == nil { 48 o.TagsPoolOptions = pool.NewObjectPoolOptions() 49 } 50 if o.TagsCapacity == 0 { 51 o.TagsCapacity = defaultCapacityOptions 52 } 53 if o.TagsMaxCapacity == 0 { 54 o.TagsMaxCapacity = defaultMaxCapacityOptions 55 } 56 if o.TagsIteratorPoolOptions == nil { 57 o.TagsIteratorPoolOptions = pool.NewObjectPoolOptions() 58 } 59 return o 60 } 61 62 // NewPool constructs a new simple Pool. 63 func NewPool( 64 bytesPool pool.CheckedBytesPool, 65 opts PoolOptions, 66 ) Pool { 67 opts = opts.defaultsIfNotSet() 68 69 p := &simplePool{ 70 bytesPool: bytesPool, 71 pool: pool.NewObjectPool(opts.IDPoolOptions), 72 tagArrayPool: newTagArrayPool(tagArrayPoolOpts{ 73 Options: opts.TagsPoolOptions, 74 Capacity: opts.TagsCapacity, 75 MaxCapacity: opts.TagsMaxCapacity, 76 }), 77 itersPool: pool.NewObjectPool(opts.TagsIteratorPoolOptions), 78 } 79 p.pool.Init(func() interface{} { 80 return &id{pool: p} 81 }) 82 p.tagArrayPool.Init() 83 p.itersPool.Init(func() interface{} { 84 return newTagSliceIter(Tags{}, nil, p) 85 }) 86 87 return p 88 } 89 90 type simplePool struct { 91 bytesPool pool.CheckedBytesPool 92 pool pool.ObjectPool 93 tagArrayPool tagArrayPool 94 itersPool pool.ObjectPool 95 } 96 97 func (p *simplePool) GetBinaryID(ctx context.Context, v checked.Bytes) ID { 98 id := p.BinaryID(v) 99 ctx.RegisterFinalizer(id) 100 return id 101 } 102 103 func (p *simplePool) BinaryID(v checked.Bytes) ID { 104 id := p.pool.Get().(*id) 105 v.IncRef() 106 id.pool, id.data = p, v 107 return id 108 } 109 110 func (p *simplePool) GetBinaryTag( 111 ctx context.Context, 112 name checked.Bytes, 113 value checked.Bytes, 114 ) Tag { 115 return Tag{ 116 Name: TagName(p.GetBinaryID(ctx, name)), 117 Value: TagValue(p.GetBinaryID(ctx, value)), 118 } 119 } 120 121 func (p *simplePool) BinaryTag( 122 name checked.Bytes, 123 value checked.Bytes, 124 ) Tag { 125 return Tag{ 126 Name: TagName(p.BinaryID(name)), 127 Value: TagValue(p.BinaryID(value)), 128 } 129 } 130 131 func (p *simplePool) GetStringID(ctx context.Context, v string) ID { 132 id := p.StringID(v) 133 ctx.RegisterFinalizer(id) 134 return id 135 } 136 137 func (p *simplePool) StringID(v string) ID { 138 data := p.bytesPool.Get(len(v)) 139 data.IncRef() 140 data.AppendAll([]byte(v)) 141 data.DecRef() 142 143 return p.BinaryID(data) 144 } 145 146 func (p *simplePool) GetTagsIterator(c context.Context) TagsIterator { 147 iter := p.itersPool.Get().(*tagSliceIter) 148 c.RegisterCloser(iter) 149 return iter 150 } 151 152 func (p *simplePool) TagsIterator() TagsIterator { 153 return p.itersPool.Get().(*tagSliceIter) 154 } 155 156 func (p *simplePool) Tags() Tags { 157 return Tags{ 158 values: p.tagArrayPool.Get(), 159 pool: p, 160 } 161 } 162 163 func (p *simplePool) Put(v ID) { 164 p.pool.Put(v) 165 } 166 167 func (p *simplePool) PutTag(t Tag) { 168 p.Put(t.Name) 169 p.Put(t.Value) 170 } 171 172 func (p *simplePool) PutTags(t Tags) { 173 p.tagArrayPool.Put(t.values) 174 } 175 176 func (p *simplePool) PutTagsIterator(iter TagsIterator) { 177 iter.Reset(Tags{}) 178 p.itersPool.Put(iter) 179 } 180 181 func (p *simplePool) GetStringTag(ctx context.Context, name string, value string) Tag { 182 return Tag{ 183 Name: TagName(p.GetStringID(ctx, name)), 184 Value: TagValue(p.GetStringID(ctx, value)), 185 } 186 } 187 188 func (p *simplePool) StringTag(name string, value string) Tag { 189 return Tag{ 190 Name: TagName(p.StringID(name)), 191 Value: TagValue(p.StringID(value)), 192 } 193 } 194 195 func (p *simplePool) Clone(existing ID) ID { 196 var ( 197 id = p.pool.Get().(*id) 198 data = existing.Bytes() 199 newData = p.bytesPool.Get(len(data)) 200 ) 201 202 newData.IncRef() 203 newData.AppendAll(data) 204 205 id.pool, id.data = p, newData 206 207 return id 208 } 209 210 func (p *simplePool) CloneTag(t Tag) Tag { 211 return Tag{ 212 Name: p.Clone(t.Name), 213 Value: p.Clone(t.Value), 214 } 215 } 216 217 func (p *simplePool) CloneTags(t Tags) Tags { 218 tags := p.tagArrayPool.Get()[:0] 219 for _, tag := range t.Values() { 220 tags = append(tags, p.CloneTag(tag)) 221 } 222 return Tags{ 223 values: tags, 224 pool: p, 225 } 226 }