github.com/pingcap/badger@v1.5.1-0.20230103063557-828f39b09b6d/table/merge_iterator_test.go (about) 1 /* 2 * Copyright 2017 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package table 18 19 import ( 20 "bytes" 21 "fmt" 22 "sort" 23 "testing" 24 25 "github.com/pingcap/badger/cache/z" 26 "github.com/pingcap/badger/y" 27 "github.com/stretchr/testify/require" 28 ) 29 30 type SimpleIterator struct { 31 keys []y.Key 32 vals [][]byte 33 idx int 34 reversed bool 35 36 latestOffs []int 37 verIdx int 38 } 39 40 var ( 41 closeCount int 42 ) 43 44 func (s *SimpleIterator) Next() { 45 if !s.reversed { 46 s.idx++ 47 s.verIdx = 0 48 } else { 49 s.idx-- 50 s.verIdx = 0 51 } 52 } 53 54 func (s *SimpleIterator) NextVersion() bool { 55 nextEntryOff := len(s.keys) 56 if s.idx+1 < len(s.latestOffs) { 57 nextEntryOff = s.latestOffs[s.idx+1] 58 } 59 if s.entryIdx()+1 < nextEntryOff { 60 s.verIdx++ 61 return true 62 } 63 return false 64 } 65 66 func (s *SimpleIterator) Rewind() { 67 if !s.reversed { 68 s.idx = 0 69 s.verIdx = 0 70 } else { 71 s.idx = len(s.latestOffs) - 1 72 s.verIdx = 0 73 } 74 } 75 76 func (s *SimpleIterator) Seek(key []byte) { 77 s.idx = sort.Search(len(s.latestOffs), func(i int) bool { 78 return bytes.Compare(s.keys[s.latestOffs[i]].UserKey, key) >= 0 79 }) 80 s.verIdx = 0 81 if s.reversed { 82 if !s.Valid() || !bytes.Equal(s.Key().UserKey, key) { 83 s.idx-- 84 } 85 } 86 } 87 88 func (s *SimpleIterator) Key() y.Key { 89 return s.keys[s.entryIdx()] 90 } 91 92 func (s *SimpleIterator) entryIdx() int { 93 return s.latestOffs[s.idx] + s.verIdx 94 } 95 96 func (s *SimpleIterator) Value() y.ValueStruct { 97 return y.ValueStruct{ 98 Value: s.vals[s.entryIdx()], 99 UserMeta: []byte{55}, 100 Meta: 0, 101 } 102 } 103 func (s *SimpleIterator) FillValue(vs *y.ValueStruct) { 104 vs.Value = s.vals[s.entryIdx()] 105 vs.UserMeta = []byte{55} // arbitrary value for test 106 vs.Meta = 0 107 } 108 func (s *SimpleIterator) Valid() bool { 109 return s.idx >= 0 && s.idx < len(s.latestOffs) 110 } 111 112 func (s *SimpleIterator) Close() error { 113 return nil 114 } 115 116 func newSimpleIterator(keys []string, vals []string, reversed bool) *SimpleIterator { 117 k := make([]y.Key, len(keys)) 118 v := make([][]byte, len(vals)) 119 lastestOffs := make([]int, len(keys)) 120 y.Assert(len(keys) == len(vals)) 121 for i := 0; i < len(keys); i++ { 122 k[i] = y.KeyWithTs([]byte(keys[i]), 0) 123 v[i] = []byte(vals[i]) 124 lastestOffs[i] = i 125 } 126 return &SimpleIterator{ 127 keys: k, 128 vals: v, 129 idx: -1, 130 reversed: reversed, 131 latestOffs: lastestOffs, 132 } 133 } 134 135 func newMultiVersionSimpleIterator(maxVersion, minVersion uint64, reversed bool) *SimpleIterator { 136 var latestOffs []int 137 var keys []y.Key 138 var vals [][]byte 139 for i := 0; i < 100; i++ { 140 latestOffs = append(latestOffs, len(keys)) 141 key := []byte(fmt.Sprintf("key%.3d", i)) 142 for j := maxVersion; j >= minVersion; j-- { 143 keys = append(keys, y.KeyWithTs(key, j)) 144 vals = append(vals, key) 145 if z.FastRand()%4 == 0 { 146 break 147 } 148 } 149 } 150 return &SimpleIterator{ 151 keys: keys, 152 vals: vals, 153 idx: 0, 154 reversed: reversed, 155 latestOffs: latestOffs, 156 } 157 } 158 159 func getAll(it y.Iterator) ([]string, []string) { 160 var keys, vals []string 161 for ; it.Valid(); it.Next() { 162 k := it.Key() 163 keys = append(keys, string(k.UserKey)) 164 v := it.Value() 165 vals = append(vals, string(v.Value)) 166 } 167 return keys, vals 168 } 169 170 func TestSimpleIterator(t *testing.T) { 171 keys := []string{"1", "2", "3"} 172 vals := []string{"v1", "v2", "v3"} 173 it := newSimpleIterator(keys, vals, false) 174 defer it.Close() 175 it.Rewind() 176 k, v := getAll(it) 177 require.EqualValues(t, keys, k) 178 require.EqualValues(t, vals, v) 179 } 180 181 func reversed(a []string) []string { 182 var out []string 183 for i := len(a) - 1; i >= 0; i-- { 184 out = append(out, a[i]) 185 } 186 return out 187 } 188 189 func TestMergeSingle(t *testing.T) { 190 keys := []string{"1", "2", "3"} 191 vals := []string{"v1", "v2", "v3"} 192 it := newSimpleIterator(keys, vals, false) 193 mergeIt := NewMergeIterator([]y.Iterator{it}, false) 194 defer mergeIt.Close() 195 mergeIt.Rewind() 196 k, v := getAll(mergeIt) 197 require.EqualValues(t, keys, k) 198 require.EqualValues(t, vals, v) 199 } 200 201 func TestMergeSingleReversed(t *testing.T) { 202 keys := []string{"1", "2", "3"} 203 vals := []string{"v1", "v2", "v3"} 204 it := newSimpleIterator(keys, vals, true) 205 mergeIt := NewMergeIterator([]y.Iterator{it}, true) 206 defer mergeIt.Close() 207 mergeIt.Rewind() 208 k, v := getAll(mergeIt) 209 require.EqualValues(t, reversed(keys), k) 210 require.EqualValues(t, reversed(vals), v) 211 } 212 213 func TestMergeMore(t *testing.T) { 214 it1 := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, false) 215 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, false) 216 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, false) 217 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, false) 218 219 mergeIt := NewMergeIterator([]y.Iterator{it1, it2, it3, it4}, false) 220 defer mergeIt.Close() 221 expectedKeys := []string{"1", "2", "3", "5", "7", "9"} 222 expectedVals := []string{"a1", "b2", "a3", "b5", "a7", "d9"} 223 mergeIt.Rewind() 224 k, v := getAll(mergeIt) 225 require.EqualValues(t, expectedKeys, k) 226 require.EqualValues(t, expectedVals, v) 227 } 228 229 // Ensure MergeIterator satisfies the Iterator interface 230 func TestMergeIteratorNested(t *testing.T) { 231 keys := []string{"1", "2", "3"} 232 vals := []string{"v1", "v2", "v3"} 233 it := newSimpleIterator(keys, vals, false) 234 mergeIt := NewMergeIterator([]y.Iterator{it}, false) 235 mergeIt2 := NewMergeIterator([]y.Iterator{mergeIt}, false) 236 defer mergeIt2.Close() 237 mergeIt2.Rewind() 238 k, v := getAll(mergeIt2) 239 require.EqualValues(t, keys, k) 240 require.EqualValues(t, vals, v) 241 } 242 243 func TestMergeIteratorSeek(t *testing.T) { 244 it := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, false) 245 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, false) 246 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, false) 247 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, false) 248 mergeIt := NewMergeIterator([]y.Iterator{it, it2, it3, it4}, false) 249 defer mergeIt.Close() 250 mergeIt.Seek([]byte("4")) 251 k, v := getAll(mergeIt) 252 require.EqualValues(t, []string{"5", "7", "9"}, k) 253 require.EqualValues(t, []string{"b5", "a7", "d9"}, v) 254 } 255 256 func TestMergeIteratorSeekReversed(t *testing.T) { 257 it := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, true) 258 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, true) 259 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, true) 260 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, true) 261 mergeIt := NewMergeIterator([]y.Iterator{it, it2, it3, it4}, true) 262 defer mergeIt.Close() 263 mergeIt.Seek([]byte("5")) 264 k, v := getAll(mergeIt) 265 require.EqualValues(t, []string{"5", "3", "2", "1"}, k) 266 require.EqualValues(t, []string{"b5", "a3", "b2", "a1"}, v) 267 } 268 269 func TestMergeIteratorSeekInvalid(t *testing.T) { 270 it := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, false) 271 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, false) 272 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, false) 273 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, false) 274 mergeIt := NewMergeIterator([]y.Iterator{it, it2, it3, it4}, false) 275 defer mergeIt.Close() 276 mergeIt.Seek([]byte("f")) 277 require.False(t, mergeIt.Valid()) 278 } 279 280 func TestMergeIteratorSeekInvalidReversed(t *testing.T) { 281 it := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, true) 282 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, true) 283 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, true) 284 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, true) 285 mergeIt := NewMergeIterator([]y.Iterator{it, it2, it3, it4}, true) 286 defer mergeIt.Close() 287 mergeIt.Seek([]byte("0")) 288 require.False(t, mergeIt.Valid()) 289 } 290 291 func TestMergeIteratorDuplicate(t *testing.T) { 292 it1 := newSimpleIterator([]string{"0", "1", "2"}, []string{"0", "1", "2"}, false) 293 it2 := newSimpleIterator([]string{"1"}, []string{"1"}, false) 294 it3 := newSimpleIterator([]string{"2"}, []string{"2"}, false) 295 it := NewMergeIterator([]y.Iterator{it3, it2, it1}, false) 296 defer it.Close() 297 var cnt int 298 for it.Rewind(); it.Valid(); it.Next() { 299 require.EqualValues(t, cnt+48, it.Key().UserKey[0]) 300 cnt++ 301 } 302 require.Equal(t, 3, cnt) 303 } 304 305 func TestMultiVersionMergeIterator(t *testing.T) { 306 for _, reverse := range []bool{true, false} { 307 it1 := newMultiVersionSimpleIterator(100, 90, reverse) 308 it2 := newMultiVersionSimpleIterator(90, 80, reverse) 309 it3 := newMultiVersionSimpleIterator(80, 70, reverse) 310 it4 := newMultiVersionSimpleIterator(70, 60, reverse) 311 it := NewMergeIterator([]y.Iterator{it1, it2, it3, it4}, reverse) 312 313 it.Rewind() 314 curKey := it.Key().UserKey 315 for i := 1; i < 100; i++ { 316 it.Next() 317 require.True(t, it.Valid()) 318 require.False(t, bytes.Equal(curKey, it.Key().UserKey)) 319 curKey = it.Key().UserKey 320 curVer := it.Key().Version 321 for it.NextVersion() { 322 require.True(t, it.Key().Version < curVer) 323 curVer = it.Key().Version 324 } 325 } 326 for i := 0; i < 100; i++ { 327 key := []byte(fmt.Sprintf("key%.3d", z.FastRand()%100)) 328 it.Seek(key) 329 require.True(t, it.Valid()) 330 require.EqualValues(t, it.Key().UserKey, key) 331 curVer := it.Key().Version 332 for it.NextVersion() { 333 require.True(t, it.Key().Version < curVer) 334 curVer = it.Key().Version 335 } 336 require.True(t, curVer <= 70) 337 } 338 it.Close() 339 } 340 } 341 342 func BenchmarkMergeIterator(b *testing.B) { 343 num := 2 344 simpleIters := make([]y.Iterator, num) 345 for i := 0; i < num; i++ { 346 simpleIters[i] = new(SimpleIterator) 347 } 348 for i := 0; i < num*100; i += num { 349 for j := 0; j < num; j++ { 350 iter := simpleIters[j].(*SimpleIterator) 351 iter.keys = append(iter.keys, y.KeyWithTs([]byte(fmt.Sprintf("key%08d", i+j)), 0)) 352 } 353 } 354 mergeIter := NewMergeIterator(simpleIters, false) 355 defer mergeIter.Close() 356 b.ResetTimer() 357 for i := 0; i < b.N; i++ { 358 mergeIter.Rewind() 359 for mergeIter.Valid() { 360 mergeIter.Key() 361 mergeIter.Next() 362 } 363 } 364 }