github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/encoding/proto/benchmarks_test.go (about)

     1  // Copyright (c) 2019 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package proto
    22  
    23  import (
    24  	"fmt"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/jhump/protoreflect/dynamic"
    29  	"github.com/m3db/m3/src/dbnode/encoding"
    30  	"github.com/m3db/m3/src/dbnode/namespace"
    31  	"github.com/m3db/m3/src/dbnode/ts"
    32  	"github.com/m3db/m3/src/dbnode/x/xio"
    33  	"github.com/m3db/m3/src/x/context"
    34  	xtime "github.com/m3db/m3/src/x/time"
    35  )
    36  
    37  func BenchmarkEncoder(b *testing.B) {
    38  	b.Run("with non custom encoded fields enabled", func(b *testing.B) {
    39  		benchmarkEncoder(b, true)
    40  	})
    41  	b.Run("with non custom encoded fields disabled", func(b *testing.B) {
    42  		benchmarkEncoder(b, false)
    43  	})
    44  }
    45  
    46  func benchmarkEncoder(b *testing.B, nonCustomFieldsEnabled bool) {
    47  	var (
    48  		_, messagesBytes = testMessages(100, nonCustomFieldsEnabled)
    49  		start            = xtime.Now()
    50  		encoder          = NewEncoder(start, encoding.NewOptions())
    51  	)
    52  	encoder.SetSchema(namespace.GetTestSchemaDescr(testVLSchema))
    53  
    54  	for i := 0; i < b.N; i++ {
    55  		start = start.Add(time.Second)
    56  		for _, protoBytes := range messagesBytes {
    57  			if err := encoder.Encode(ts.Datapoint{TimestampNanos: start},
    58  				xtime.Second, protoBytes); err != nil {
    59  				panic(err)
    60  			}
    61  		}
    62  	}
    63  }
    64  
    65  func BenchmarkIterator(b *testing.B) {
    66  	b.Run("with non custom encoded fields enabled", func(b *testing.B) {
    67  		benchmarkIterator(b, true)
    68  	})
    69  	b.Run("with non custom encoded fields disabled", func(b *testing.B) {
    70  		benchmarkIterator(b, false)
    71  	})
    72  }
    73  
    74  func benchmarkIterator(b *testing.B, nonCustomFieldsEnabled bool) {
    75  	ctx := context.NewBackground()
    76  	defer ctx.Close()
    77  
    78  	var (
    79  		_, messagesBytes = testMessages(100, nonCustomFieldsEnabled)
    80  		start            = xtime.Now()
    81  		encodingOpts     = encoding.NewOptions()
    82  		encoder          = NewEncoder(start, encodingOpts)
    83  		schema           = namespace.GetTestSchemaDescr(testVLSchema)
    84  	)
    85  	encoder.SetSchema(schema)
    86  
    87  	for _, protoBytes := range messagesBytes {
    88  		start = start.Add(time.Second)
    89  		if err := encoder.Encode(ts.Datapoint{TimestampNanos: start},
    90  			xtime.Second, protoBytes); err != nil {
    91  			panic(err)
    92  		}
    93  	}
    94  
    95  	stream, ok := encoder.Stream(ctx)
    96  	if !ok {
    97  		panic("encoder had no stream")
    98  	}
    99  	segment, err := stream.Segment()
   100  	handleErr(err)
   101  
   102  	iterator := NewIterator(stream, schema, encodingOpts)
   103  	reader := xio.NewSegmentReader(segment)
   104  	for i := 0; i < b.N; i++ {
   105  		reader.Reset(segment)
   106  		iterator.Reset(reader, schema)
   107  		for iterator.Next() {
   108  			iterator.Current()
   109  		}
   110  		handleErr(iterator.Err())
   111  	}
   112  }
   113  
   114  func testMessages(numMessages int, includeAttributes bool) ([]*dynamic.Message, [][]byte) {
   115  	var (
   116  		messages      = make([]*dynamic.Message, 0, numMessages)
   117  		messagesBytes = make([][]byte, 0, numMessages)
   118  	)
   119  	for i := 0; i < numMessages; i++ {
   120  		m := dynamic.NewMessage(testVLSchema)
   121  		m.SetFieldByName("latitude", float64(i))
   122  		m.SetFieldByName("longitude", float64(i))
   123  		m.SetFieldByName("deliveryID", []byte(fmt.Sprintf("some-really-really-really-really-long-id-%d", i)))
   124  		if includeAttributes {
   125  			m.SetFieldByName("attributes", map[string]string{
   126  				fmt.Sprintf("key1_%d", i): fmt.Sprintf("val1_%d", i),
   127  				fmt.Sprintf("key2_%d", i): fmt.Sprintf("val2_%d", i),
   128  				fmt.Sprintf("key3_%d", i): fmt.Sprintf("val3_%d", i),
   129  			})
   130  		}
   131  
   132  		bytes, err := m.Marshal()
   133  		handleErr(err)
   134  
   135  		messagesBytes = append(messagesBytes, bytes)
   136  		messages = append(messages, m)
   137  	}
   138  	return messages, messagesBytes
   139  }
   140  
   141  func handleErr(e error) {
   142  	if e != nil {
   143  		panic(e)
   144  	}
   145  }