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  }