Skip to content
This repository was archived by the owner on Oct 17, 2018. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions protocol/msgpack/aggregated_encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package msgpack

/*
import (
"testing"

Expand Down Expand Up @@ -178,3 +179,4 @@ func TestAggregatedEncoderReset(t *testing.T) {
encoder.Reset(NewBufferedEncoder())
require.NoError(t, testAggregatedEncodeMetricWithPolicy(encoder, testMetric, testPolicy))
}
*/
6 changes: 3 additions & 3 deletions protocol/msgpack/aggregated_iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ func NewAggregatedIterator(reader io.Reader, opts AggregatedIteratorOptions) Agg
if opts == nil {
opts = NewAggregatedIteratorOptions()
}
readerBufferSize := opts.ReaderBufferSize()
baseIteratorOpts := opts.BaseIteratorOptions()
return &aggregatedIterator{
ignoreHigherVersion: opts.IgnoreHigherVersion(),
iteratorBase: newBaseIterator(reader, readerBufferSize),
metric: NewRawMetric(nil, readerBufferSize),
iteratorBase: newBaseIterator(reader, baseIteratorOpts),
metric: NewRawMetric(nil, baseIteratorOpts),
iteratorPool: opts.IteratorPool(),
}
}
Expand Down
2 changes: 2 additions & 0 deletions protocol/msgpack/aggregated_iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package msgpack

/*
import (
"io"
"testing"
Expand Down Expand Up @@ -205,3 +206,4 @@ func TestAggregatedIteratorClose(t *testing.T) {
require.NoError(t, it.Err())
require.True(t, it.(*aggregatedIterator).closed)
}
*/
2 changes: 2 additions & 0 deletions protocol/msgpack/aggregated_roundtrip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package msgpack

/*
import (
"bytes"
"fmt"
Expand Down Expand Up @@ -272,3 +273,4 @@ func TestAggregatedEncodeDecodeStress(t *testing.T) {
validateAggregatedRoundtripWithEncoderAndIterator(t, encoder, iterator, inputs...)
}
}
*/
125 changes: 125 additions & 0 deletions protocol/msgpack/base_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package msgpack

import (
"bytes"
"math/rand"
"testing"
)

var (
smallFloat64s []float64
mediumFloat64s []float64
largeFloat64s []float64
)

func BenchmarkEncodeFloat64NativeSmall(b *testing.B) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: take it or leave it, but could combine these into a single benchmark with a table, for example:

func BenchmarkFloat64(b *testing.B) {
  // initialize float slice

  benchmarks := []struct {
    name string
    vals []float64
    encoding encodingType
  } {
    {
      name: "EncodeNativeSmall"
      vals: smallFloat64a,
      encoding: nonPackedEncoding,
    },
    ...
  }

  for _, bm := range benchmarks {
    b.Run(bm.name, func(b *testing.B) {
      for i := 0; i < b.N; i++ {
        AppendFloat(dst[:0], bm.float, bm.fmt, bm.prec, bm.bitSize)
      }
    })
  }
}

benchEncode(b, smallFloat64s, nonPackedEncoding)
}

func BenchmarkEncodeFloat64NativeMedium(b *testing.B) {
benchEncode(b, mediumFloat64s, nonPackedEncoding)
}

func BenchmarkEncodeFloat64NativeLarge(b *testing.B) {
benchEncode(b, largeFloat64s, nonPackedEncoding)
}

func BenchmarkEncodeFloat64PackedSmall(b *testing.B) {
benchEncode(b, smallFloat64s, packedEncoding)
}

func BenchmarkEncodeFloat64PackedMedium(b *testing.B) {
benchEncode(b, mediumFloat64s, packedEncoding)
}

func BenchmarkEncodeFloat64PackedLarge(b *testing.B) {
benchEncode(b, largeFloat64s, packedEncoding)
}

func BenchmarkDecodeFloat64NativeSmall(b *testing.B) {
benchDecode(b, smallFloat64s, nonPackedEncoding)
}

func BenchmarkDecodeFloat64NativeMedium(b *testing.B) {
benchDecode(b, mediumFloat64s, nonPackedEncoding)
}

func BenchmarkDecodeFloat64NativeLarge(b *testing.B) {
benchDecode(b, largeFloat64s, nonPackedEncoding)
}

func BenchmarkDecodeFloat64PackedSmall(b *testing.B) {
benchDecode(b, smallFloat64s, packedEncoding)
}

func BenchmarkDecodeFloat64PackedMedium(b *testing.B) {
benchDecode(b, mediumFloat64s, packedEncoding)
}

func BenchmarkDecodeFloat64PackedLarge(b *testing.B) {
benchDecode(b, largeFloat64s, packedEncoding)
}

func benchEncode(b *testing.B, values []float64, encodingType encodingType) {
buffer := NewBufferedEncoder()
encoder := newBaseEncoder(buffer)
b.ResetTimer()
for n := 0; n < b.N; n++ {
encoder.encodeFloat64Slice(values, encodingType)
}
}

func benchDecode(b *testing.B, values []float64, encodingType encodingType) {
encoded := encodedBytes(values, encodingType)
iterator := newBaseIterator(nil, nil)
b.ResetTimer()
for n := 0; n < b.N; n++ {
reader := bytes.NewBuffer(encoded)
iterator.reset(reader)
iterator.decodeFloat64Slice(encodingType)
}
}

func encodedBytes(values []float64, encodingType encodingType) []byte {
buffer := NewBufferedEncoder()
encoder := newBaseEncoder(buffer)
encoder.encodeFloat64Slice(values, encodingType)
return buffer.Bytes()
}

func init() {
smallFloat64s = make([]float64, 16)
for i := 0; i < len(smallFloat64s); i++ {
smallFloat64s[i] = rand.Float64() * 100
}

mediumFloat64s = make([]float64, 1120)
for i := 0; i < len(mediumFloat64s); i++ {
mediumFloat64s[i] = rand.Float64() * 100
}

largeFloat64s = make([]float64, 65536)
for i := 0; i < len(largeFloat64s); i++ {
largeFloat64s[i] = rand.Float64() * 100
}
}
59 changes: 58 additions & 1 deletion protocol/msgpack/base_encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@
package msgpack

import (
"math"

"github.com/m3db/m3metrics/metric/id"
"github.com/m3db/m3metrics/policy"
)

type encodeVarintFn func(value int64)
type encodeBoolFn func(value bool)
type encodeFloat64Fn func(value float64)
type encodeFloat64SliceFn func(value []float64, encodingType encodingType)
type encodeBytesFn func(value []byte)
type encodeBytesLenFn func(value int)
type encodeArrayLenFn func(value int)
Expand All @@ -37,10 +40,12 @@ type encodePolicyFn func(p policy.Policy)
// baseEncoder is the base encoder that provides common encoding APIs.
type baseEncoder struct {
bufEncoder BufferedEncoder
tmpBuf []byte
encodeErr error
encodeVarintFn encodeVarintFn
encodeBoolFn encodeBoolFn
encodeFloat64Fn encodeFloat64Fn
encodeFloat64SliceFn encodeFloat64SliceFn
encodeBytesFn encodeBytesFn
encodeBytesLenFn encodeBytesLenFn
encodeArrayLenFn encodeArrayLenFn
Expand All @@ -49,11 +54,15 @@ type baseEncoder struct {
}

func newBaseEncoder(encoder BufferedEncoder) encoderBase {
enc := &baseEncoder{bufEncoder: encoder}
enc := &baseEncoder{
bufEncoder: encoder,
tmpBuf: make([]byte, numBytesInFloat64),
}

enc.encodeVarintFn = enc.encodeVarintInternal
enc.encodeBoolFn = enc.encodeBoolInternal
enc.encodeFloat64Fn = enc.encodeFloat64Internal
enc.encodeFloat64SliceFn = enc.encodeFloat64SliceInternal
enc.encodeBytesFn = enc.encodeBytesInternal
enc.encodeBytesLenFn = enc.encodeBytesLenInternal
enc.encodeArrayLenFn = enc.encodeArrayLenInternal
Expand All @@ -79,6 +88,10 @@ func (enc *baseEncoder) encodeArrayLen(value int) { enc.encode
func (enc *baseEncoder) encodeStoragePolicy(p policy.StoragePolicy) { enc.encodeStoragePolicyFn(p) }
func (enc *baseEncoder) encodePolicy(p policy.Policy) { enc.encodePolicyFn(p) }

func (enc *baseEncoder) encodeFloat64Slice(values []float64, encodingType encodingType) {
enc.encodeFloat64SliceFn(values, encodingType)
}

func (enc *baseEncoder) reset(encoder BufferedEncoder) {
enc.bufEncoder = encoder
enc.encodeErr = nil
Expand Down Expand Up @@ -187,6 +200,50 @@ func (enc *baseEncoder) encodeFloat64Internal(value float64) {
enc.encodeErr = enc.bufEncoder.EncodeFloat64(value)
}

func (enc *baseEncoder) encodeFloat64SliceInternal(values []float64, encodingType encodingType) {
if encodingType == nonPackedEncoding {
enc.encodeFloat64SliceNative(values)
return
}
enc.encodeFloat64SlicePacked(values)
}

// encodeFloat64SliceNative encodes a slice of float64 values using
// native MessagePack encoding.
func (enc *baseEncoder) encodeFloat64SliceNative(values []float64) {
if enc.encodeErr != nil {
return
}
if enc.encodeErr = enc.bufEncoder.EncodeArrayLen(len(values)); enc.encodeErr != nil {
return
}
for _, v := range values {
if enc.encodeErr = enc.bufEncoder.EncodeFloat64(v); enc.encodeErr != nil {
return
}
}
}

// encodeFloat64SliceNative encodes a slice of float64 values using
// more compact encoding by encoding the float64 values as byte.
func (enc *baseEncoder) encodeFloat64SlicePacked(values []float64) {
if enc.encodeErr != nil {
return
}
numValues := len(values)
numBytes := numValues * numBytesInFloat64
if enc.encodeErr = enc.bufEncoder.EncodeBytesLen(numBytes); enc.encodeErr != nil {
return
}
for i := 0; i < numValues; i++ {
byteOrder.PutUint64(enc.tmpBuf, math.Float64bits(values[i]))
_, enc.encodeErr = enc.bufEncoder.Buffer().Write(enc.tmpBuf)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to write the bytes on at a time or would it perhaps be beneficial to write them only into the buffer in the loop and then write the entire buffer once outside the loop?

if enc.encodeErr != nil {
return
}
}
}

func (enc *baseEncoder) encodeBytesInternal(value []byte) {
if enc.encodeErr != nil {
return
Expand Down
Loading