github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/chunk/disk_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 "fmt" 18 "io" 19 "io/ioutil" 20 "math/rand" 21 "os" 22 "path/filepath" 23 "strconv" 24 "strings" 25 "testing" 26 27 "github.com/cznic/mathutil" 28 "github.com/whtcorpsinc/check" 29 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 30 "github.com/whtcorpsinc/milevadb/config" 31 "github.com/whtcorpsinc/milevadb/types" 32 "github.com/whtcorpsinc/milevadb/types/json" 33 ) 34 35 func initChunks(numChk, numRow int) ([]*Chunk, []*types.FieldType) { 36 fields := []*types.FieldType{ 37 types.NewFieldType(allegrosql.TypeVarString), 38 types.NewFieldType(allegrosql.TypeLonglong), 39 types.NewFieldType(allegrosql.TypeVarString), 40 types.NewFieldType(allegrosql.TypeLonglong), 41 types.NewFieldType(allegrosql.TypeJSON), 42 } 43 44 chks := make([]*Chunk, 0, numChk) 45 for chkIdx := 0; chkIdx < numChk; chkIdx++ { 46 chk := NewChunkWithCapacity(fields, numRow) 47 for rowIdx := 0; rowIdx < numRow; rowIdx++ { 48 data := int64(chkIdx*numRow + rowIdx) 49 chk.AppendString(0, fmt.Sprint(data)) 50 chk.AppendNull(1) 51 chk.AppendNull(2) 52 chk.AppendInt64(3, data) 53 if chkIdx%2 == 0 { 54 chk.AppendJSON(4, json.CreateBinary(fmt.Sprint(data))) 55 } else { 56 chk.AppendNull(4) 57 } 58 } 59 chks = append(chks, chk) 60 } 61 return chks, fields 62 } 63 64 func (s *testChunkSuite) TestListInDisk(c *check.C) { 65 numChk, numRow := 2, 2 66 chks, fields := initChunks(numChk, numRow) 67 l := NewListInDisk(fields) 68 defer func() { 69 err := l.Close() 70 c.Check(err, check.IsNil) 71 c.Check(l.disk, check.NotNil) 72 _, err = os.Stat(l.disk.Name()) 73 c.Check(os.IsNotExist(err), check.IsTrue) 74 }() 75 for _, chk := range chks { 76 err := l.Add(chk) 77 c.Check(err, check.IsNil) 78 } 79 c.Assert(strings.HasPrefix(l.disk.Name(), filepath.Join(os.TemFIDelir(), "oom-use-tmp-storage")), check.Equals, true) 80 c.Check(l.NumChunks(), check.Equals, numChk) 81 c.Check(l.GetDiskTracker().BytesConsumed() > 0, check.IsTrue) 82 83 for chkIdx := 0; chkIdx < numChk; chkIdx++ { 84 for rowIdx := 0; rowIdx < numRow; rowIdx++ { 85 event, err := l.GetRow(RowPtr{ChkIdx: uint32(chkIdx), RowIdx: uint32(rowIdx)}) 86 c.Check(err, check.IsNil) 87 c.Check(event.GetCausetRow(fields), check.DeepEquals, chks[chkIdx].GetRow(rowIdx).GetCausetRow(fields)) 88 } 89 } 90 } 91 92 func BenchmarkListInDiskAdd(b *testing.B) { 93 numChk, numRow := 1, 2 94 chks, fields := initChunks(numChk, numRow) 95 chk := chks[0] 96 l := NewListInDisk(fields) 97 defer l.Close() 98 99 b.ResetTimer() 100 for i := 0; i < b.N; i++ { 101 err := l.Add(chk) 102 if err != nil { 103 b.Fatal(err) 104 } 105 } 106 } 107 108 func BenchmarkListInDiskGetRow(b *testing.B) { 109 numChk, numRow := 10000, 2 110 chks, fields := initChunks(numChk, numRow) 111 l := NewListInDisk(fields) 112 defer l.Close() 113 for _, chk := range chks { 114 err := l.Add(chk) 115 if err != nil { 116 b.Fatal(err) 117 } 118 } 119 rand.Seed(0) 120 ptrs := make([]RowPtr, 0, b.N) 121 for i := 0; i < mathutil.Min(b.N, 10000); i++ { 122 ptrs = append(ptrs, RowPtr{ 123 ChkIdx: rand.Uint32() % uint32(numChk), 124 RowIdx: rand.Uint32() % uint32(numRow), 125 }) 126 } 127 for i := 10000; i < cap(ptrs); i++ { 128 ptrs = append(ptrs, ptrs[i%10000]) 129 } 130 b.ResetTimer() 131 for i := 0; i < b.N; i++ { 132 _, err := l.GetRow(ptrs[i]) 133 if err != nil { 134 b.Fatal(err) 135 } 136 } 137 } 138 139 type listInDiskWriteDisk struct { 140 ListInDisk 141 } 142 143 func newListInDiskWriteDisk(fieldTypes []*types.FieldType) (*listInDiskWriteDisk, error) { 144 l := listInDiskWriteDisk{*NewListInDisk(fieldTypes)} 145 disk, err := ioutil.TempFile(config.GetGlobalConfig().TempStoragePath, strconv.Itoa(l.diskTracker.Label())) 146 if err != nil { 147 return nil, err 148 } 149 l.disk = disk 150 l.w = disk 151 return &l, nil 152 } 153 154 func (l *listInDiskWriteDisk) GetRow(ptr RowPtr) (event Row, err error) { 155 err = l.flush() 156 if err != nil { 157 return 158 } 159 off := l.offsets[ptr.ChkIdx][ptr.RowIdx] 160 161 r := io.NewSectionReader(l.disk, off, l.offWrite-off) 162 format := rowInDisk{numDefCaus: len(l.fieldTypes)} 163 _, err = format.ReadFrom(r) 164 if err != nil { 165 return event, err 166 } 167 event = format.toMutRow(l.fieldTypes).ToRow() 168 return event, err 169 } 170 171 func checkRow(c *check.C, row1, row2 Row) { 172 c.Assert(row1.GetString(0), check.Equals, row2.GetString(0)) 173 c.Assert(row1.GetInt64(1), check.Equals, row2.GetInt64(1)) 174 c.Assert(row1.GetString(2), check.Equals, row2.GetString(2)) 175 c.Assert(row1.GetInt64(3), check.Equals, row2.GetInt64(3)) 176 if !row1.IsNull(4) { 177 c.Assert(row1.GetJSON(4).String(), check.Equals, row2.GetJSON(4).String()) 178 } 179 } 180 181 func testListInDisk(c *check.C) { 182 numChk, numRow := 10, 1000 183 chks, fields := initChunks(numChk, numRow) 184 lChecksum := NewListInDisk(fields) 185 defer lChecksum.Close() 186 lDisk, err := newListInDiskWriteDisk(fields) 187 c.Assert(err, check.IsNil) 188 defer lDisk.Close() 189 for _, chk := range chks { 190 err := lChecksum.Add(chk) 191 c.Assert(err, check.IsNil) 192 err = lDisk.Add(chk) 193 c.Assert(err, check.IsNil) 194 } 195 196 var ptrs []RowPtr 197 for i := 0; i < numChk; i++ { 198 for j := 0; j < numRow; j++ { 199 ptrs = append(ptrs, RowPtr{ 200 ChkIdx: uint32(i), 201 RowIdx: uint32(j), 202 }) 203 } 204 } 205 206 for _, rowPtr := range ptrs { 207 row1, err := lChecksum.GetRow(rowPtr) 208 c.Assert(err, check.IsNil) 209 row2, err := lDisk.GetRow(rowPtr) 210 c.Assert(err, check.IsNil) 211 checkRow(c, row1, row2) 212 } 213 } 214 215 func (s *testChunkSuite) TestListInDiskWithChecksum(c *check.C) { 216 defer config.RestoreFunc()() 217 config.UFIDelateGlobal(func(conf *config.Config) { 218 conf.Security.SpilledFileEncryptionMethod = config.SpilledFileEncryptionMethodPlaintext 219 }) 220 testListInDisk(c) 221 222 } 223 224 func (s *testChunkSuite) TestListInDiskWithChecksumAndEncrypt(c *check.C) { 225 defer config.RestoreFunc()() 226 config.UFIDelateGlobal(func(conf *config.Config) { 227 conf.Security.SpilledFileEncryptionMethod = config.SpilledFileEncryptionMethodAES128CTR 228 }) 229 testListInDisk(c) 230 }