Skip to content
This repository was archived by the owner on Oct 17, 2018. It is now read-only.

[WIP] Optimize encoding and decoding float64 slices - #117

Open
xichen2020 wants to merge 7 commits into
masterfrom
xichen-optimize-float64s-encoding-decoding
Open

[WIP] Optimize encoding and decoding float64 slices#117
xichen2020 wants to merge 7 commits into
masterfrom
xichen-optimize-float64s-encoding-decoding

Conversation

@xichen2020

Copy link
Copy Markdown
Contributor

cc @cw9 @jeromefroe

Need to fix the tests that have been commented out so marking it as work in progress, but the core implementation is complete. Benchmarks have shown promising results with the optimizations in this PR for encoding and decoding float64 slices, which is a significant portion of the overall encoding and decoding work.

Benchmark results (native is the current implementation, packed is the new implementation)

BenchmarkEncodeFloat64NativeSmall-8    	 2000000	       545 ns/op
BenchmarkEncodeFloat64NativeMedium-8   	   50000	     36431 ns/op
BenchmarkEncodeFloat64NativeLarge-8    	    1000	   1864905 ns/op
BenchmarkEncodeFloat64PackedSmall-8    	 5000000	       406 ns/op
BenchmarkEncodeFloat64PackedMedium-8   	  100000	     19447 ns/op
BenchmarkEncodeFloat64PackedLarge-8    	    2000	   1038561 ns/op
BenchmarkDecodeFloat64NativeSmall-8    	 1000000	      1066 ns/op
BenchmarkDecodeFloat64NativeMedium-8   	   20000	     65211 ns/op
BenchmarkDecodeFloat64NativeLarge-8    	     500	   3669564 ns/op
BenchmarkDecodeFloat64PackedSmall-8    	 5000000	       298 ns/op
BenchmarkDecodeFloat64PackedMedium-8   	  200000	     12088 ns/op
BenchmarkDecodeFloat64PackedLarge-8    	    2000	    658596 ns/op

As shown above, with the packed encoding/decoding, for medium sized []float64 with 1120 values, the new encoder is ~1.9x faster than the current encoder and the new decoder is ~5.4x faster than the current decoder.

@coveralls

coveralls commented Nov 25, 2017

Copy link
Copy Markdown

Coverage Status

Coverage decreased (-4.5%) to 84.188% when pulling 3e1ee15 on xichen-optimize-float64s-encoding-decoding into 29ec093 on master.

@jeromefroe jeromefroe left a comment

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.

Any idea why the packed format is so much more performant than the native one?

}
decoded, pool := it.getFloat64SliceFor(numValues)
for i := 0; i < numValues; i++ {
decoded = append(decoded, it.decodeFloat64())

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.

Seems in decodeFloat64SlicePacked we check the error after decoding each value, should we do the same here?

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)
      }
    })
  }
}

}
if numValues <= it.largeFloatsSize {
newCapcity := int(math.Max(float64(numValues), float64(cap(it.cachedFloat64s)*2)))
if newCapcity > it.largeFloatsSize {

@jeromefroe jeromefroe Nov 25, 2017

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.

Why not just make the capacity of it.cachedFloat64s to it.largeFloatSize when we initialize the iterator? It seems like after enough time it will reach that value, no?

}
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?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants