1package msgpack_test 2 3import ( 4 "bytes" 5 "io/ioutil" 6 "math" 7 "testing" 8 "time" 9 10 "github.com/vmihailenco/msgpack" 11) 12 13func BenchmarkDiscard(b *testing.B) { 14 enc := msgpack.NewEncoder(ioutil.Discard) 15 16 b.ResetTimer() 17 18 for i := 0; i < b.N; i++ { 19 if err := enc.Encode(nil); err != nil { 20 b.Fatal(err) 21 } 22 if err := enc.Encode("hello"); err != nil { 23 b.Fatal(err) 24 } 25 } 26} 27 28func benchmarkEncodeDecode(b *testing.B, src, dst interface{}) { 29 var buf bytes.Buffer 30 enc := msgpack.NewEncoder(&buf) 31 dec := msgpack.NewDecoder(&buf) 32 33 b.ResetTimer() 34 35 for i := 0; i < b.N; i++ { 36 if err := enc.Encode(src); err != nil { 37 b.Fatal(err) 38 } 39 if err := dec.Decode(dst); err != nil { 40 b.Fatal(err) 41 } 42 } 43} 44 45func BenchmarkBool(b *testing.B) { 46 var dst bool 47 benchmarkEncodeDecode(b, true, &dst) 48} 49 50func BenchmarkInt0(b *testing.B) { 51 var dst int 52 benchmarkEncodeDecode(b, 1, &dst) 53} 54 55func BenchmarkInt1(b *testing.B) { 56 var dst int 57 benchmarkEncodeDecode(b, -33, &dst) 58} 59 60func BenchmarkInt2(b *testing.B) { 61 var dst int 62 benchmarkEncodeDecode(b, 128, &dst) 63} 64 65func BenchmarkInt4(b *testing.B) { 66 var dst int 67 benchmarkEncodeDecode(b, 32768, &dst) 68} 69 70func BenchmarkInt8(b *testing.B) { 71 var dst int 72 benchmarkEncodeDecode(b, int64(2147483648), &dst) 73} 74 75func BenchmarkInt32(b *testing.B) { 76 var dst int32 77 benchmarkEncodeDecode(b, int32(0), &dst) 78} 79 80func BenchmarkTime(b *testing.B) { 81 var dst time.Time 82 benchmarkEncodeDecode(b, time.Now(), &dst) 83} 84 85func BenchmarkDuration(b *testing.B) { 86 var dst time.Duration 87 benchmarkEncodeDecode(b, time.Hour, &dst) 88} 89 90func BenchmarkByteSlice(b *testing.B) { 91 src := make([]byte, 1024) 92 var dst []byte 93 benchmarkEncodeDecode(b, src, &dst) 94} 95 96func BenchmarkByteArray(b *testing.B) { 97 var src [1024]byte 98 var dst [1024]byte 99 benchmarkEncodeDecode(b, src, &dst) 100} 101 102func BenchmarkByteArrayPtr(b *testing.B) { 103 var src [1024]byte 104 var dst [1024]byte 105 benchmarkEncodeDecode(b, &src, &dst) 106} 107 108func BenchmarkMapStringString(b *testing.B) { 109 src := map[string]string{ 110 "hello": "world", 111 "foo": "bar", 112 } 113 var dst map[string]string 114 benchmarkEncodeDecode(b, src, &dst) 115} 116 117func BenchmarkMapStringStringPtr(b *testing.B) { 118 src := map[string]string{ 119 "hello": "world", 120 "foo": "bar", 121 } 122 var dst map[string]string 123 dstptr := &dst 124 benchmarkEncodeDecode(b, src, &dstptr) 125} 126 127func BenchmarkMapStringInterface(b *testing.B) { 128 src := map[string]interface{}{ 129 "hello": "world", 130 "foo": "bar", 131 } 132 var dst map[string]interface{} 133 benchmarkEncodeDecode(b, src, &dst) 134} 135 136func BenchmarkMapIntInt(b *testing.B) { 137 src := map[int]int{ 138 1: 10, 139 2: 20, 140 } 141 var dst map[int]int 142 benchmarkEncodeDecode(b, src, &dst) 143} 144 145func BenchmarkStringSlice(b *testing.B) { 146 src := []string{"hello", "world"} 147 var dst []string 148 benchmarkEncodeDecode(b, src, &dst) 149} 150 151func BenchmarkStringSlicePtr(b *testing.B) { 152 src := []string{"hello", "world"} 153 var dst []string 154 dstptr := &dst 155 benchmarkEncodeDecode(b, src, &dstptr) 156} 157 158type benchmarkStruct struct { 159 Name string 160 Age int 161 Colors []string 162 Data []byte 163 CreatedAt time.Time 164 UpdatedAt time.Time 165} 166 167type benchmarkStruct2 struct { 168 Name string 169 Age int 170 Colors []string 171 Data []byte 172 CreatedAt time.Time 173 UpdatedAt time.Time 174} 175 176var _ msgpack.CustomEncoder = (*benchmarkStruct2)(nil) 177var _ msgpack.CustomDecoder = (*benchmarkStruct2)(nil) 178 179func (s *benchmarkStruct2) EncodeMsgpack(enc *msgpack.Encoder) error { 180 return enc.EncodeMulti( 181 s.Name, 182 s.Colors, 183 s.Age, 184 s.Data, 185 s.CreatedAt, 186 s.UpdatedAt, 187 ) 188} 189 190func (s *benchmarkStruct2) DecodeMsgpack(dec *msgpack.Decoder) error { 191 return dec.DecodeMulti( 192 &s.Name, 193 &s.Colors, 194 &s.Age, 195 &s.Data, 196 &s.CreatedAt, 197 &s.UpdatedAt, 198 ) 199} 200 201func structForBenchmark() *benchmarkStruct { 202 return &benchmarkStruct{ 203 Name: "Hello World", 204 Colors: []string{"red", "orange", "yellow", "green", "blue", "violet"}, 205 Age: math.MaxInt32, 206 Data: make([]byte, 1024), 207 CreatedAt: time.Now(), 208 UpdatedAt: time.Now(), 209 } 210} 211 212func structForBenchmark2() *benchmarkStruct2 { 213 return &benchmarkStruct2{ 214 Name: "Hello World", 215 Colors: []string{"red", "orange", "yellow", "green", "blue", "violet"}, 216 Age: math.MaxInt32, 217 Data: make([]byte, 1024), 218 CreatedAt: time.Now(), 219 UpdatedAt: time.Now(), 220 } 221} 222 223func BenchmarkStructVmihailencoMsgpack(b *testing.B) { 224 in := structForBenchmark() 225 out := new(benchmarkStruct) 226 227 b.ResetTimer() 228 229 for i := 0; i < b.N; i++ { 230 buf, err := msgpack.Marshal(in) 231 if err != nil { 232 b.Fatal(err) 233 } 234 235 err = msgpack.Unmarshal(buf, out) 236 if err != nil { 237 b.Fatal(err) 238 } 239 } 240} 241 242func BenchmarkStructMarshal(b *testing.B) { 243 in := structForBenchmark() 244 245 b.ResetTimer() 246 247 for i := 0; i < b.N; i++ { 248 _, err := msgpack.Marshal(in) 249 if err != nil { 250 b.Fatal(err) 251 } 252 } 253} 254 255func BenchmarkStructUnmarshal(b *testing.B) { 256 in := structForBenchmark() 257 buf, err := msgpack.Marshal(in) 258 if err != nil { 259 b.Fatal(err) 260 } 261 out := new(benchmarkStruct) 262 263 b.ResetTimer() 264 265 for i := 0; i < b.N; i++ { 266 err = msgpack.Unmarshal(buf, out) 267 if err != nil { 268 b.Fatal(err) 269 } 270 } 271} 272 273func BenchmarkStructManual(b *testing.B) { 274 in := structForBenchmark2() 275 out := new(benchmarkStruct2) 276 277 b.ResetTimer() 278 279 for i := 0; i < b.N; i++ { 280 buf, err := msgpack.Marshal(in) 281 if err != nil { 282 b.Fatal(err) 283 } 284 285 err = msgpack.Unmarshal(buf, out) 286 if err != nil { 287 b.Fatal(err) 288 } 289 } 290} 291 292type benchmarkStructPartially struct { 293 Name string 294 Age int 295} 296 297func BenchmarkStructUnmarshalPartially(b *testing.B) { 298 in := structForBenchmark() 299 buf, err := msgpack.Marshal(in) 300 if err != nil { 301 b.Fatal(err) 302 } 303 out := new(benchmarkStructPartially) 304 305 b.ResetTimer() 306 307 for i := 0; i < b.N; i++ { 308 err = msgpack.Unmarshal(buf, out) 309 if err != nil { 310 b.Fatal(err) 311 } 312 } 313} 314 315func BenchmarkQuery(b *testing.B) { 316 var records []map[string]interface{} 317 for i := 0; i < 1000; i++ { 318 record := map[string]interface{}{ 319 "id": i, 320 "attrs": map[string]interface{}{"phone": i}, 321 } 322 records = append(records, record) 323 } 324 325 bs, err := msgpack.Marshal(records) 326 if err != nil { 327 b.Fatal(err) 328 } 329 330 dec := msgpack.NewDecoder(bytes.NewBuffer(bs)) 331 332 b.ResetTimer() 333 334 for i := 0; i < b.N; i++ { 335 dec.Reset(bytes.NewBuffer(bs)) 336 337 values, err := dec.Query("10.attrs.phone") 338 if err != nil { 339 b.Fatal(err) 340 } 341 if values[0].(int8) != 10 { 342 b.Fatalf("%v != %d", values[0], 10) 343 } 344 } 345} 346