package msgpack_test import ( "bytes" "math" "testing" "time" "github.com/vmihailenco/msgpack" ) func benchmarkEncodeDecode(b *testing.B, src, dst interface{}) { var buf bytes.Buffer dec := msgpack.NewDecoder(&buf) enc := msgpack.NewEncoder(&buf) b.ResetTimer() for i := 0; i < b.N; i++ { if err := enc.Encode(src); err != nil { b.Fatal(err) } if err := dec.Decode(dst); err != nil { b.Fatal(err) } } } func BenchmarkBool(b *testing.B) { var dst bool benchmarkEncodeDecode(b, true, &dst) } func BenchmarkInt0(b *testing.B) { var dst int benchmarkEncodeDecode(b, 1, &dst) } func BenchmarkInt1(b *testing.B) { var dst int benchmarkEncodeDecode(b, -33, &dst) } func BenchmarkInt2(b *testing.B) { var dst int benchmarkEncodeDecode(b, 128, &dst) } func BenchmarkInt4(b *testing.B) { var dst int benchmarkEncodeDecode(b, 32768, &dst) } func BenchmarkInt8(b *testing.B) { var dst int benchmarkEncodeDecode(b, int64(2147483648), &dst) } func BenchmarkInt32(b *testing.B) { var dst int32 benchmarkEncodeDecode(b, int32(0), &dst) } func BenchmarkTime(b *testing.B) { var dst time.Time benchmarkEncodeDecode(b, time.Now(), &dst) } func BenchmarkDuration(b *testing.B) { var dst time.Duration benchmarkEncodeDecode(b, time.Hour, &dst) } func BenchmarkByteSlice(b *testing.B) { src := make([]byte, 1024) var dst []byte benchmarkEncodeDecode(b, src, &dst) } func BenchmarkByteArray(b *testing.B) { var src [1024]byte var dst [1024]byte benchmarkEncodeDecode(b, src, &dst) } func BenchmarkMapStringString(b *testing.B) { src := map[string]string{ "hello": "world", "foo": "bar", } var dst map[string]string benchmarkEncodeDecode(b, src, &dst) } func BenchmarkMapStringStringPtr(b *testing.B) { src := map[string]string{ "hello": "world", "foo": "bar", } var dst map[string]string dstptr := &dst benchmarkEncodeDecode(b, src, &dstptr) } func BenchmarkMapStringInterface(b *testing.B) { src := map[string]interface{}{ "hello": "world", "foo": "bar", } var dst map[string]interface{} benchmarkEncodeDecode(b, src, &dst) } func BenchmarkMapIntInt(b *testing.B) { src := map[int]int{ 1: 10, 2: 20, } var dst map[int]int benchmarkEncodeDecode(b, src, &dst) } func BenchmarkStringSlice(b *testing.B) { src := []string{"hello", "world"} var dst []string benchmarkEncodeDecode(b, src, &dst) } func BenchmarkStringSlicePtr(b *testing.B) { src := []string{"hello", "world"} var dst []string dstptr := &dst benchmarkEncodeDecode(b, src, &dstptr) } type benchmarkStruct struct { Name string Age int Colors []string Data []byte CreatedAt time.Time UpdatedAt time.Time } type benchmarkStruct2 struct { Name string Age int Colors []string Data []byte CreatedAt time.Time UpdatedAt time.Time } var _ msgpack.CustomEncoder = (*benchmarkStruct2)(nil) var _ msgpack.CustomDecoder = (*benchmarkStruct2)(nil) func (s *benchmarkStruct2) EncodeMsgpack(enc *msgpack.Encoder) error { return enc.Encode( s.Name, s.Colors, s.Age, s.Data, s.CreatedAt, s.UpdatedAt, ) } func (s *benchmarkStruct2) DecodeMsgpack(dec *msgpack.Decoder) error { return dec.Decode( &s.Name, &s.Colors, &s.Age, &s.Data, &s.CreatedAt, &s.UpdatedAt, ) } func structForBenchmark() *benchmarkStruct { return &benchmarkStruct{ Name: "Hello World", Colors: []string{"red", "orange", "yellow", "green", "blue", "violet"}, Age: math.MaxInt32, Data: make([]byte, 1024), CreatedAt: time.Now(), UpdatedAt: time.Now(), } } func structForBenchmark2() *benchmarkStruct2 { return &benchmarkStruct2{ Name: "Hello World", Colors: []string{"red", "orange", "yellow", "green", "blue", "violet"}, Age: math.MaxInt32, Data: make([]byte, 1024), CreatedAt: time.Now(), UpdatedAt: time.Now(), } } func BenchmarkStructVmihailencoMsgpack(b *testing.B) { in := structForBenchmark() out := new(benchmarkStruct) b.ResetTimer() for i := 0; i < b.N; i++ { buf, err := msgpack.Marshal(in) if err != nil { b.Fatal(err) } err = msgpack.Unmarshal(buf, out) if err != nil { b.Fatal(err) } } } func BenchmarkStructMarshal(b *testing.B) { in := structForBenchmark() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := msgpack.Marshal(in) if err != nil { b.Fatal(err) } } } func BenchmarkStructUnmarshal(b *testing.B) { in := structForBenchmark() buf, err := msgpack.Marshal(in) if err != nil { b.Fatal(err) } out := new(benchmarkStruct) b.ResetTimer() for i := 0; i < b.N; i++ { err = msgpack.Unmarshal(buf, out) if err != nil { b.Fatal(err) } } } func BenchmarkStructManual(b *testing.B) { in := structForBenchmark2() out := new(benchmarkStruct2) b.ResetTimer() for i := 0; i < b.N; i++ { buf, err := msgpack.Marshal(in) if err != nil { b.Fatal(err) } err = msgpack.Unmarshal(buf, out) if err != nil { b.Fatal(err) } } } type benchmarkStructPartially struct { Name string Age int } func BenchmarkStructUnmarshalPartially(b *testing.B) { in := structForBenchmark() buf, err := msgpack.Marshal(in) if err != nil { b.Fatal(err) } out := new(benchmarkStructPartially) b.ResetTimer() for i := 0; i < b.N; i++ { err = msgpack.Unmarshal(buf, out) if err != nil { b.Fatal(err) } } } func BenchmarkQuery(b *testing.B) { var records []map[string]interface{} for i := 0; i < 1000; i++ { record := map[string]interface{}{ "id": i, "attrs": map[string]interface{}{"phone": i}, } records = append(records, record) } bs, err := msgpack.Marshal(records) if err != nil { b.Fatal(err) } dec := msgpack.NewDecoder(bytes.NewBuffer(bs)) b.ResetTimer() for i := 0; i < b.N; i++ { dec.Reset(bytes.NewBuffer(bs)) values, err := dec.Query("10.attrs.phone") if err != nil { b.Fatal(err) } if values[0].(int8) != 10 { b.Fatalf("%v != %d", values[0], 10) } } }