github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/sink/codec/craft/buffer.go (about) 1 // Copyright 2021 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License") 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.orglicensesLICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package craft 15 16 // Utility functions for buffer allocation 17 func newBufferSize(oldSize int) int { 18 var newSize int 19 if oldSize > 128 { 20 newSize = oldSize + 128 21 } else { 22 if oldSize > 0 { 23 newSize = oldSize * 2 24 } else { 25 newSize = 8 26 } 27 } 28 return newSize 29 } 30 31 // generic slice allocator 32 type sliceAllocator[T any] struct { 33 buffer []T 34 offset int 35 } 36 37 //nolint:unused 38 func (b *sliceAllocator[T]) realloc(old []T, newSize int) []T { 39 n := b.alloc(newSize) 40 copy(n, old) 41 return n 42 } 43 44 func (b *sliceAllocator[T]) alloc(size int) []T { 45 if len(b.buffer)-b.offset < size { 46 if size > len(b.buffer)/4 { 47 // large allocation 48 return make([]T, size) 49 } 50 b.buffer = make([]T, len(b.buffer)) 51 b.offset = 0 52 } 53 result := b.buffer[b.offset : b.offset+size] 54 b.offset += size 55 return result 56 } 57 58 //nolint:unused 59 func (b *sliceAllocator[T]) one(x T) []T { 60 r := b.alloc(1) 61 r[0] = x 62 return r 63 } 64 65 func newGenericSliceAllocator[T any](batchSize int) *sliceAllocator[T] { 66 return &sliceAllocator[T]{buffer: make([]T, batchSize)} 67 } 68 69 // SliceAllocator for different slice types 70 type SliceAllocator struct { 71 intAllocator *sliceAllocator[int] 72 int64Allocator *sliceAllocator[int64] 73 uint64Allocator *sliceAllocator[uint64] 74 stringAllocator *sliceAllocator[string] 75 nullableStringAllocator *sliceAllocator[*string] 76 byteAllocator *sliceAllocator[byte] 77 bytesAllocator *sliceAllocator[[]byte] 78 columnGroupAllocator *sliceAllocator[*columnGroup] 79 rowChangedEventAllocator *sliceAllocator[rowChangedEvent] 80 } 81 82 // NewSliceAllocator creates a new slice allocator with given batch allocation size. 83 func NewSliceAllocator(batchSize int) *SliceAllocator { 84 return &SliceAllocator{ 85 intAllocator: newGenericSliceAllocator[int](batchSize), 86 int64Allocator: newGenericSliceAllocator[int64](batchSize), 87 uint64Allocator: newGenericSliceAllocator[uint64](batchSize), 88 stringAllocator: newGenericSliceAllocator[string](batchSize), 89 nullableStringAllocator: newGenericSliceAllocator[*string](batchSize), 90 byteAllocator: newGenericSliceAllocator[byte](batchSize), 91 bytesAllocator: newGenericSliceAllocator[[]byte](batchSize), 92 columnGroupAllocator: newGenericSliceAllocator[*columnGroup](batchSize), 93 rowChangedEventAllocator: newGenericSliceAllocator[rowChangedEvent](batchSize), 94 } 95 } 96 97 func (b *SliceAllocator) intSlice(size int) []int { 98 return b.intAllocator.alloc(size) 99 } 100 101 //nolint:unused 102 func (b *SliceAllocator) oneIntSlice(x int) []int { 103 return b.intAllocator.one(x) 104 } 105 106 //nolint:unused 107 func (b *SliceAllocator) resizeIntSlice(old []int, newSize int) []int { 108 return b.intAllocator.realloc(old, newSize) 109 } 110 111 func (b *SliceAllocator) int64Slice(size int) []int64 { 112 return b.int64Allocator.alloc(size) 113 } 114 115 //nolint:unused 116 func (b *SliceAllocator) oneInt64Slice(x int64) []int64 { 117 return b.int64Allocator.one(x) 118 } 119 120 func (b *SliceAllocator) resizeInt64Slice(old []int64, newSize int) []int64 { 121 return b.int64Allocator.realloc(old, newSize) 122 } 123 124 func (b *SliceAllocator) uint64Slice(size int) []uint64 { 125 return b.uint64Allocator.alloc(size) 126 } 127 128 func (b *SliceAllocator) oneUint64Slice(x uint64) []uint64 { 129 return b.uint64Allocator.one(x) 130 } 131 132 func (b *SliceAllocator) resizeUint64Slice(old []uint64, newSize int) []uint64 { 133 return b.uint64Allocator.realloc(old, newSize) 134 } 135 136 func (b *SliceAllocator) stringSlice(size int) []string { 137 return b.stringAllocator.alloc(size) 138 } 139 140 //nolint:unused 141 func (b *SliceAllocator) oneStringSlice(x string) []string { 142 return b.stringAllocator.one(x) 143 } 144 145 //nolint:unused 146 func (b *SliceAllocator) resizeStringSlice(old []string, newSize int) []string { 147 return b.stringAllocator.realloc(old, newSize) 148 } 149 150 func (b *SliceAllocator) nullableStringSlice(size int) []*string { 151 return b.nullableStringAllocator.alloc(size) 152 } 153 154 func (b *SliceAllocator) oneNullableStringSlice(x *string) []*string { 155 return b.nullableStringAllocator.one(x) 156 } 157 158 func (b *SliceAllocator) resizeNullableStringSlice(old []*string, newSize int) []*string { 159 return b.nullableStringAllocator.realloc(old, newSize) 160 } 161 162 func (b *SliceAllocator) byteSlice(size int) []byte { 163 return b.byteAllocator.alloc(size) 164 } 165 166 //nolint:unused 167 func (b *SliceAllocator) oneByteSlice(x byte) []byte { 168 return b.byteAllocator.one(x) 169 } 170 171 //nolint:unused 172 func (b *SliceAllocator) resizeByteSlice(old []byte, newSize int) []byte { 173 return b.byteAllocator.realloc(old, newSize) 174 } 175 176 func (b *SliceAllocator) bytesSlice(size int) [][]byte { 177 return b.bytesAllocator.alloc(size) 178 } 179 180 //nolint:unused 181 func (b *SliceAllocator) oneBytesSlice(x []byte) [][]byte { 182 return b.bytesAllocator.one(x) 183 } 184 185 //nolint:unused 186 func (b *SliceAllocator) resizeBytesSlice(old [][]byte, newSize int) [][]byte { 187 return b.bytesAllocator.realloc(old, newSize) 188 } 189 190 func (b *SliceAllocator) columnGroupSlice(size int) []*columnGroup { 191 return b.columnGroupAllocator.alloc(size) 192 } 193 194 //nolint:unused 195 func (b *SliceAllocator) oneColumnGroupSlice(x *columnGroup) []*columnGroup { 196 return b.columnGroupAllocator.one(x) 197 } 198 199 //nolint:unused 200 func (b *SliceAllocator) resizeColumnGroupSlice(old []*columnGroup, newSize int) []*columnGroup { 201 return b.columnGroupAllocator.realloc(old, newSize) 202 } 203 204 //nolint:unused 205 func (b *SliceAllocator) rowChangedEventSlice(size int) []rowChangedEvent { 206 return b.rowChangedEventAllocator.alloc(size) 207 } 208 209 //nolint:unused 210 func (b *SliceAllocator) oneRowChangedEventSlice(x rowChangedEvent) []rowChangedEvent { 211 return b.rowChangedEventAllocator.one(x) 212 } 213 214 func (b *SliceAllocator) resizeRowChangedEventSlice(old []rowChangedEvent, newSize int) []rowChangedEvent { 215 return b.rowChangedEventAllocator.realloc(old, newSize) 216 }