github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/perf/codec-perf-rig/main.go (about) 1 // Copyright 2019 Dolthub, 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // This file incorporates work covered by the following copyright and 16 // permission notice: 17 // 18 // Copyright 2016 Attic Labs, Inc. All rights reserved. 19 // Licensed under the Apache License, version 2.0: 20 // http://www.apache.org/licenses/LICENSE-2.0 21 22 package main 23 24 import ( 25 "bytes" 26 "context" 27 "encoding/binary" 28 "fmt" 29 "time" 30 31 flag "github.com/juju/gnuflag" 32 33 "github.com/dolthub/dolt/go/store/chunks" 34 "github.com/dolthub/dolt/go/store/d" 35 "github.com/dolthub/dolt/go/store/datas" 36 "github.com/dolthub/dolt/go/store/prolly/tree" 37 "github.com/dolthub/dolt/go/store/types" 38 "github.com/dolthub/dolt/go/store/util/profile" 39 ) 40 41 var ( 42 count = flag.Uint64("count", 100000, "number of elements") 43 blobSize = flag.Uint64("blobsize", 2<<24 /* 32MB */, "size of blob of create") 44 ) 45 46 const numberSize = uint64(8) 47 const strPrefix = "i am a 32 bytes.....%12d" 48 const stringSize = uint64(32) 49 const structSize = uint64(64) 50 51 func main() { 52 profile.RegisterProfileFlags(flag.CommandLine) 53 flag.Parse(true) 54 55 buildCount := *count 56 insertCount := buildCount 57 defer profile.MaybeStartProfile().Stop() 58 59 collectionTypes := []string{"List", "Set", "Map"} 60 buildFns := []buildCollectionFn{buildList, buildSet, buildMap} 61 buildIncrFns := []buildCollectionFn{buildListIncrementally, buildSetIncrementally, buildMapIncrementally} 62 readFns := []readCollectionFn{readList, readSet, readMap} 63 64 elementTypes := []string{"numbers (8 B)", "strings (32 B)", "structs (64 B)"} 65 elementSizes := []uint64{numberSize, stringSize, structSize} 66 valueFns := []createValueFn{createNumber, createString, createStruct} 67 68 ctx := context.Background() 69 70 for i, colType := range collectionTypes { 71 fmt.Printf("Testing %s: \t\tbuild %d\t\t\tscan %d\t\t\tinsert %d\n", colType, buildCount, buildCount, insertCount) 72 73 for j, elementType := range elementTypes { 74 valueFn := valueFns[j] 75 76 // Build One-Time 77 storage := &chunks.MemoryStorage{} 78 cs := storage.NewViewWithDefaultFormat() 79 ns := tree.NewNodeStore(cs) 80 vrw := types.NewValueStore(cs) 81 db := datas.NewTypesDatabase(vrw, ns) 82 ds, err := db.GetDataset(ctx, "test") 83 d.Chk.NoError(err) 84 t1 := time.Now() 85 col := buildFns[i](ctx, vrw, buildCount, valueFn) 86 ds, err = datas.CommitValue(ctx, db, ds, col) 87 d.Chk.NoError(err) 88 buildDuration := time.Since(t1) 89 90 // Read 91 t1 = time.Now() 92 val, ok, err := ds.MaybeHeadValue() 93 d.Chk.NoError(err) 94 d.Chk.True(ok) 95 col = val.(types.Collection) 96 readFns[i](ctx, col) 97 readDuration := time.Since(t1) 98 99 // Build Incrementally 100 storage = &chunks.MemoryStorage{} 101 cs = storage.NewViewWithDefaultFormat() 102 ns = tree.NewNodeStore(cs) 103 vrw = types.NewValueStore(cs) 104 db = datas.NewTypesDatabase(vrw, ns) 105 ds, err = db.GetDataset(ctx, "test") 106 d.Chk.NoError(err) 107 t1 = time.Now() 108 col = buildIncrFns[i](ctx, vrw, insertCount, valueFn) 109 ds, err = datas.CommitValue(ctx, db, ds, col) 110 d.Chk.NoError(err) 111 incrDuration := time.Since(t1) 112 113 elementSize := elementSizes[j] 114 buildSize := elementSize * buildCount 115 incrSize := elementSize * insertCount 116 117 fmt.Printf("%s\t\t%s\t\t%s\t\t%s\n", elementType, rate(buildDuration, buildSize), rate(readDuration, buildSize), rate(incrDuration, incrSize)) 118 } 119 fmt.Println() 120 } 121 122 fmt.Printf("Testing Blob: \t\tbuild %d MB\t\t\tscan %d MB\n", *blobSize/1000000, *blobSize/1000000) 123 124 storage := &chunks.MemoryStorage{} 125 cs := storage.NewViewWithDefaultFormat() 126 ns := tree.NewNodeStore(cs) 127 vrw := types.NewValueStore(cs) 128 db := datas.NewTypesDatabase(vrw, ns) 129 ds, err := db.GetDataset(ctx, "test") 130 d.Chk.NoError(err) 131 132 blobBytes := makeBlobBytes(*blobSize) 133 t1 := time.Now() 134 blob, err := types.NewBlob(ctx, vrw, bytes.NewReader(blobBytes)) 135 d.Chk.NoError(err) 136 _, err = datas.CommitValue(ctx, db, ds, blob) 137 d.Chk.NoError(err) 138 buildDuration := time.Since(t1) 139 140 db = datas.NewDatabase(storage.NewViewWithDefaultFormat()) 141 ds, err = db.GetDataset(ctx, "test") 142 d.Chk.NoError(err) 143 t1 = time.Now() 144 blobVal, ok, err := ds.MaybeHeadValue() 145 d.Chk.NoError(err) 146 d.Chk.True(ok) 147 blob = blobVal.(types.Blob) 148 buff := &bytes.Buffer{} 149 blob.Copy(ctx, buff) 150 outBytes := buff.Bytes() 151 readDuration := time.Since(t1) 152 d.PanicIfFalse(bytes.Equal(blobBytes, outBytes)) 153 fmt.Printf("\t\t\t%s\t\t%s\n\n", rate(buildDuration, *blobSize), rate(readDuration, *blobSize)) 154 } 155 156 func rate(d time.Duration, size uint64) string { 157 return fmt.Sprintf("%d ms (%.2f MB/s)", uint64(d)/1000000, float64(size)*1000/float64(d)) 158 } 159 160 type createValueFn func(i uint64) types.Value 161 type buildCollectionFn func(ctx context.Context, vrw types.ValueReadWriter, count uint64, createFn createValueFn) types.Collection 162 type readCollectionFn func(ctx context.Context, value types.Collection) 163 164 func makeBlobBytes(byteLength uint64) []byte { 165 buff := &bytes.Buffer{} 166 counter := uint64(0) 167 for uint64(buff.Len()) < byteLength { 168 err := binary.Write(buff, binary.BigEndian, counter) 169 d.Chk.NoError(err) 170 counter++ 171 } 172 return buff.Bytes() 173 } 174 175 func createString(i uint64) types.Value { 176 return types.String(fmt.Sprintf("%s%d", strPrefix, i)) 177 } 178 179 func createNumber(i uint64) types.Value { 180 return types.Float(i) 181 } 182 183 var structTemplate = types.MakeStructTemplate("S1", []string{"bool", "num", "str"}) 184 185 func createStruct(i uint64) types.Value { 186 st, err := structTemplate.NewStruct(types.Format_Default, []types.Value{ 187 types.Bool(i%2 == 0), // "bool" 188 types.Float(i), // "num" 189 types.String(fmt.Sprintf("i am a 55 bytes............................%12d", i)), // "str" 190 }) 191 192 d.Chk.NoError(err) 193 194 return st 195 } 196 197 func buildList(ctx context.Context, vrw types.ValueReadWriter, count uint64, createFn createValueFn) types.Collection { 198 values := make([]types.Value, count) 199 for i := uint64(0); i < count; i++ { 200 values[i] = createFn(i) 201 } 202 203 l, err := types.NewList(ctx, vrw, values...) 204 205 d.Chk.NoError(err) 206 207 return l 208 } 209 210 func buildListIncrementally(ctx context.Context, vrw types.ValueReadWriter, count uint64, createFn createValueFn) types.Collection { 211 l, err := types.NewList(ctx, vrw) 212 213 d.Chk.NoError(err) 214 215 le := l.Edit() 216 217 for i := uint64(0); i < count; i++ { 218 le.Append(createFn(i)) 219 } 220 221 l, err = le.List(ctx) 222 223 d.Chk.NoError(err) 224 225 return l 226 } 227 228 func readList(ctx context.Context, c types.Collection) { 229 _ = c.(types.List).IterAll(ctx, func(v types.Value, idx uint64) error { 230 return nil 231 }) 232 } 233 234 func buildSet(ctx context.Context, vrw types.ValueReadWriter, count uint64, createFn createValueFn) types.Collection { 235 values := make([]types.Value, count) 236 for i := uint64(0); i < count; i++ { 237 values[i] = createFn(i) 238 } 239 240 s, err := types.NewSet(ctx, vrw, values...) 241 242 d.Chk.NoError(err) 243 244 return s 245 } 246 247 func buildSetIncrementally(ctx context.Context, vrw types.ValueReadWriter, count uint64, createFn createValueFn) types.Collection { 248 s, err := types.NewSet(ctx, vrw) 249 d.Chk.NoError(err) 250 251 se := s.Edit() 252 for i := uint64(0); i < count; i++ { 253 se.Insert(ctx, createFn(i)) 254 } 255 256 s, err = se.Set(ctx) 257 d.Chk.NoError(err) 258 259 return s 260 } 261 262 func readSet(ctx context.Context, c types.Collection) { 263 _ = c.(types.Set).IterAll(ctx, func(v types.Value) error { 264 return nil 265 }) 266 } 267 268 func buildMap(ctx context.Context, vrw types.ValueReadWriter, count uint64, createFn createValueFn) types.Collection { 269 values := make([]types.Value, count*2) 270 for i := uint64(0); i < count*2; i++ { 271 values[i] = createFn(i) 272 } 273 274 m, err := types.NewMap(ctx, vrw, values...) 275 276 d.Chk.NoError(err) 277 278 return m 279 } 280 281 func buildMapIncrementally(ctx context.Context, vrw types.ValueReadWriter, count uint64, createFn createValueFn) types.Collection { 282 m, err := types.NewMap(ctx, vrw) 283 d.Chk.NoError(err) 284 285 me := m.Edit() 286 287 for i := uint64(0); i < count*2; i += 2 { 288 me.Set(createFn(i), createFn(i+1)) 289 } 290 291 m, err = me.Map(ctx) 292 d.Chk.NoError(err) 293 294 return m 295 } 296 297 func readMap(ctx context.Context, c types.Collection) { 298 _ = c.(types.Map).IterAll(ctx, func(k types.Value, v types.Value) error { 299 return nil 300 }) 301 }