github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/chunk/list_test.go (about) 1 // Copyright 2020 WHTCORPS INC, 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.org/licenses/LICENSE-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 chunk 15 16 import ( 17 "math" 18 "math/rand" 19 "strconv" 20 "strings" 21 "testing" 22 "time" 23 24 "github.com/cznic/mathutil" 25 "github.com/whtcorpsinc/check" 26 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 27 "github.com/whtcorpsinc/milevadb/types" 28 "github.com/whtcorpsinc/milevadb/types/json" 29 ) 30 31 func (s *testChunkSuite) TestList(c *check.C) { 32 fields := []*types.FieldType{ 33 types.NewFieldType(allegrosql.TypeLonglong), 34 } 35 l := NewList(fields, 2, 2) 36 srcChunk := NewChunkWithCapacity(fields, 32) 37 srcChunk.AppendInt64(0, 1) 38 srcRow := srcChunk.GetRow(0) 39 40 // Test basic append. 41 for i := 0; i < 5; i++ { 42 l.AppendRow(srcRow) 43 } 44 c.Assert(l.NumChunks(), check.Equals, 3) 45 c.Assert(l.Len(), check.Equals, 5) 46 c.Assert(len(l.freelist), check.Equals, 0) 47 48 // Test chunk reuse. 49 l.Reset() 50 c.Assert(len(l.freelist), check.Equals, 3) 51 52 for i := 0; i < 5; i++ { 53 l.AppendRow(srcRow) 54 } 55 c.Assert(len(l.freelist), check.Equals, 0) 56 57 // Test add chunk then append event. 58 l.Reset() 59 nChunk := NewChunkWithCapacity(fields, 32) 60 nChunk.AppendNull(0) 61 l.Add(nChunk) 62 ptr := l.AppendRow(srcRow) 63 c.Assert(l.NumChunks(), check.Equals, 2) 64 c.Assert(ptr.ChkIdx, check.Equals, uint32(1)) 65 c.Assert(ptr.RowIdx, check.Equals, uint32(0)) 66 event := l.GetRow(ptr) 67 c.Assert(event.GetInt64(0), check.Equals, int64(1)) 68 69 // Test iteration. 70 l.Reset() 71 for i := 0; i < 5; i++ { 72 tmp := NewChunkWithCapacity(fields, 32) 73 tmp.AppendInt64(0, int64(i)) 74 l.AppendRow(tmp.GetRow(0)) 75 } 76 expected := []int64{0, 1, 2, 3, 4} 77 var results []int64 78 err := l.Walk(func(r Row) error { 79 results = append(results, r.GetInt64(0)) 80 return nil 81 }) 82 c.Assert(err, check.IsNil) 83 c.Assert(results, check.DeepEquals, expected) 84 } 85 86 func (s *testChunkSuite) TestListMemoryUsage(c *check.C) { 87 fieldTypes := make([]*types.FieldType, 0, 5) 88 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat}) 89 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeVarchar}) 90 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeJSON}) 91 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeDatetime}) 92 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeDuration}) 93 94 jsonObj, err := json.ParseBinaryFromString("1") 95 c.Assert(err, check.IsNil) 96 timeObj := types.NewTime(types.FromGoTime(time.Now()), allegrosql.TypeDatetime, 0) 97 durationObj := types.Duration{Duration: math.MaxInt64, Fsp: 0} 98 99 maxChunkSize := 2 100 srcChk := NewChunkWithCapacity(fieldTypes, maxChunkSize) 101 srcChk.AppendFloat32(0, 12.4) 102 srcChk.AppendString(1, "123") 103 srcChk.AppendJSON(2, jsonObj) 104 srcChk.AppendTime(3, timeObj) 105 srcChk.AppendDuration(4, durationObj) 106 107 list := NewList(fieldTypes, maxChunkSize, maxChunkSize*2) 108 c.Assert(list.GetMemTracker().BytesConsumed(), check.Equals, int64(0)) 109 110 list.AppendRow(srcChk.GetRow(0)) 111 c.Assert(list.GetMemTracker().BytesConsumed(), check.Equals, int64(0)) 112 113 memUsage := list.chunks[0].MemoryUsage() 114 list.Reset() 115 c.Assert(list.GetMemTracker().BytesConsumed(), check.Equals, memUsage) 116 117 list.Add(srcChk) 118 c.Assert(list.GetMemTracker().BytesConsumed(), check.Equals, memUsage+srcChk.MemoryUsage()) 119 } 120 121 func (s *testChunkSuite) TestListPrePreAlloc4RowAndInsert(c *check.C) { 122 fieldTypes := make([]*types.FieldType, 0, 4) 123 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat}) 124 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeLonglong}) 125 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeNewDecimal}) 126 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeVarchar}) 127 128 srcChk := NewChunkWithCapacity(fieldTypes, 10) 129 for i := int64(0); i < 10; i++ { 130 srcChk.AppendFloat32(0, float32(i)) 131 srcChk.AppendInt64(1, i) 132 srcChk.AppendMyDecimal(2, types.NewDecFromInt(i)) 133 srcChk.AppendString(3, strings.Repeat(strconv.FormatInt(i, 10), int(i))) 134 } 135 136 srcList := NewList(fieldTypes, 3, 3) 137 destList := NewList(fieldTypes, 5, 5) 138 destRowPtr := make([]RowPtr, srcChk.NumRows()) 139 for i := 0; i < srcChk.NumRows(); i++ { 140 srcList.AppendRow(srcChk.GetRow(i)) 141 destRowPtr[i] = destList.preAlloc4Row(srcChk.GetRow(i)) 142 } 143 144 c.Assert(srcList.NumChunks(), check.Equals, 4) 145 c.Assert(destList.NumChunks(), check.Equals, 2) 146 147 iter4Src := NewIterator4List(srcList) 148 for event, i := iter4Src.Begin(), 0; event != iter4Src.End(); event, i = iter4Src.Next(), i+1 { 149 destList.Insert(destRowPtr[i], event) 150 } 151 152 iter4Dest := NewIterator4List(destList) 153 srcRow, destRow := iter4Src.Begin(), iter4Dest.Begin() 154 for ; srcRow != iter4Src.End(); srcRow, destRow = iter4Src.Next(), iter4Dest.Next() { 155 c.Assert(srcRow.GetFloat32(0), check.Equals, destRow.GetFloat32(0)) 156 c.Assert(srcRow.GetInt64(1), check.Equals, destRow.GetInt64(1)) 157 c.Assert(srcRow.GetMyDecimal(2).Compare(destRow.GetMyDecimal(2)) == 0, check.IsTrue) 158 c.Assert(srcRow.GetString(3), check.Equals, destRow.GetString(3)) 159 } 160 } 161 162 func BenchmarkListMemoryUsage(b *testing.B) { 163 fieldTypes := make([]*types.FieldType, 0, 4) 164 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat}) 165 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeVarchar}) 166 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeDatetime}) 167 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeDuration}) 168 169 chk := NewChunkWithCapacity(fieldTypes, 2) 170 timeObj := types.NewTime(types.FromGoTime(time.Now()), allegrosql.TypeDatetime, 0) 171 durationObj := types.Duration{Duration: math.MaxInt64, Fsp: 0} 172 chk.AppendFloat64(0, 123.123) 173 chk.AppendString(1, "123") 174 chk.AppendTime(2, timeObj) 175 chk.AppendDuration(3, durationObj) 176 event := chk.GetRow(0) 177 178 initCap := 50 179 list := NewList(fieldTypes, 2, 8) 180 for i := 0; i < initCap; i++ { 181 list.AppendRow(event) 182 } 183 b.ResetTimer() 184 for i := 0; i < b.N; i++ { 185 list.GetMemTracker().BytesConsumed() 186 } 187 } 188 189 func BenchmarkPreAllocList(b *testing.B) { 190 fieldTypes := make([]*types.FieldType, 0, 1) 191 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeLonglong}) 192 chk := NewChunkWithCapacity(fieldTypes, 1) 193 chk.AppendInt64(0, 1) 194 event := chk.GetRow(0) 195 196 b.ResetTimer() 197 list := NewList(fieldTypes, 1024, 1024) 198 for i := 0; i < b.N; i++ { 199 list.Reset() 200 // 32768 indicates the number of int64 rows to fill 256KB L2 cache. 201 for j := 0; j < 32768; j++ { 202 list.preAlloc4Row(event) 203 } 204 } 205 } 206 207 func BenchmarkPreAllocChunk(b *testing.B) { 208 fieldTypes := make([]*types.FieldType, 0, 1) 209 fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeLonglong}) 210 chk := NewChunkWithCapacity(fieldTypes, 1) 211 chk.AppendInt64(0, 1) 212 event := chk.GetRow(0) 213 214 b.ResetTimer() 215 finalChk := New(fieldTypes, 33000, 1024) 216 for i := 0; i < b.N; i++ { 217 finalChk.Reset() 218 for j := 0; j < 32768; j++ { 219 finalChk.preAlloc(event) 220 } 221 } 222 } 223 224 func BenchmarkListAdd(b *testing.B) { 225 numChk, numRow := 1, 2 226 chks, fields := initChunks(numChk, numRow) 227 chk := chks[0] 228 l := NewList(fields, numRow, numRow) 229 230 b.ResetTimer() 231 for i := 0; i < b.N; i++ { 232 l.Add(chk) 233 } 234 } 235 236 func BenchmarkListGetRow(b *testing.B) { 237 numChk, numRow := 10000, 2 238 chks, fields := initChunks(numChk, numRow) 239 l := NewList(fields, numRow, numRow) 240 for _, chk := range chks { 241 l.Add(chk) 242 } 243 rand.Seed(0) 244 ptrs := make([]RowPtr, 0, b.N) 245 for i := 0; i < mathutil.Min(b.N, 10000); i++ { 246 ptrs = append(ptrs, RowPtr{ 247 ChkIdx: rand.Uint32() % uint32(numChk), 248 RowIdx: rand.Uint32() % uint32(numRow), 249 }) 250 } 251 for i := 10000; i < cap(ptrs); i++ { 252 ptrs = append(ptrs, ptrs[i%10000]) 253 } 254 b.ResetTimer() 255 for i := 0; i < b.N; i++ { 256 l.GetRow(ptrs[i]) 257 } 258 }