Update benchmarks and examples (#154)

This commit is contained in:
Faye Amacker 2020-02-17 00:50:15 -06:00 committed by GitHub
parent c2085b75a3
commit 10f672e577
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 121 additions and 53 deletions

View File

@ -26,34 +26,34 @@ Benchmarks use data representing the following values:
Decoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkUnmarshal/CBOR_bool_to_Go_interface_{}-2 | 115 ns/op | 16 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_bool_to_Go_bool-2 | 91.1 ns/op | 1 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_positive_int_to_Go_interface_{}-2 | 138 ns/op | 24 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_positive_int_to_Go_uint64-2 | 104 ns/op | 8 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_negative_int_to_Go_interface_{}-2 | 138 ns/op | 24 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_negative_int_to_Go_int64-2 | 104 ns/op | 8 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_float_to_Go_interface_{}-2 | 139 ns/op | 24 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_float_to_Go_float64-2 | 102 ns/op | 8 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_bytes_to_Go_interface_{}-2 | 181 ns/op | 80 B/op | 3 allocs/op
BenchmarkUnmarshal/CBOR_bytes_to_Go_[]uint8-2 | 190 ns/op | 64 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_text_to_Go_interface_{}-2 | 211 ns/op | 80 B/op | 3 allocs/op
BenchmarkUnmarshal/CBOR_text_to_Go_string-2 | 181 ns/op | 64 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_array_to_Go_interface_{}-2 |1147 ns/op | 672 B/op | 29 allocs/op
BenchmarkUnmarshal/CBOR_array_to_Go_[]int-2 | 1138 ns/op | 272 B/op | 3 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_interface_{}-2 | 2962 ns/op | 1420 B/op | 30 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_map[string]interface_{}-2 | 3849 ns/op | 964 B/op | 19 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_map[string]string-2 | 2654 ns/op | 740 B/op | 5 allocs/op
BenchmarkUnmarshal/CBOR_bool_to_Go_interface_{}-2 | 114 ns/op | 16 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_bool_to_Go_bool-2 | 101 ns/op | 1 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_positive_int_to_Go_interface_{}-2 | 141 ns/op | 24 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_positive_int_to_Go_uint64-2 | 120 ns/op | 8 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_negative_int_to_Go_interface_{}-2 | 141 ns/op | 24 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_negative_int_to_Go_int64-2 | 120 ns/op | 8 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_float_to_Go_interface_{}-2 | 143 ns/op | 24 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_float_to_Go_float64-2 | 121 ns/op | 8 B/op | 1 allocs/op
BenchmarkUnmarshal/CBOR_bytes_to_Go_interface_{}-2 | 182 ns/op | 80 B/op | 3 allocs/op
BenchmarkUnmarshal/CBOR_bytes_to_Go_[]uint8-2 | 201 ns/op | 64 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_text_to_Go_interface_{}-2 | 213 ns/op | 80 B/op | 3 allocs/op
BenchmarkUnmarshal/CBOR_text_to_Go_string-2 | 196 ns/op | 64 B/op | 2 allocs/op
BenchmarkUnmarshal/CBOR_array_to_Go_interface_{}-2 |1094 ns/op | 672 B/op | 29 allocs/op
BenchmarkUnmarshal/CBOR_array_to_Go_[]int-2 | 1102 ns/op | 272 B/op | 3 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_interface_{}-2 | 2966 ns/op | 1420 B/op | 30 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_map[string]interface_{}-2 | 3754 ns/op | 964 B/op | 19 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_map[string]string-2 | 2621 ns/op | 740 B/op | 5 allocs/op
Encoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkMarshal/Go_bool_to_CBOR_bool-2 | 83.3 ns/op | 1 B/op | 1 allocs/op
BenchmarkMarshal/Go_uint64_to_CBOR_positive_int-2 | 93.4 ns/op | 16 B/op | 1 allocs/op
BenchmarkMarshal/Go_int64_to_CBOR_negative_int-2 | 88.3 ns/op | 3 B/op | 1 allocs/op
BenchmarkMarshal/Go_float64_to_CBOR_float-2 | 95.4 ns/op | 16 B/op | 1 allocs/op
BenchmarkMarshal/Go_[]uint8_to_CBOR_bytes-2 | 119 ns/op | 32 B/op | 1 allocs/op
BenchmarkMarshal/Go_string_to_CBOR_text-2 | 114 ns/op | 48 B/op | 1 allocs/op
BenchmarkMarshal/Go_[]int_to_CBOR_array-2 | 470 ns/op | 32 B/op | 1 allocs/op
BenchmarkMarshal/Go_map[string]string_to_CBOR_map-2 | 2064 ns/op | 576 B/op | 28 allocs/op
BenchmarkMarshal/Go_bool_to_CBOR_bool-2 | 88.1 ns/op | 1 B/op | 1 allocs/op
BenchmarkMarshal/Go_uint64_to_CBOR_positive_int-2 | 97.3 ns/op | 16 B/op | 1 allocs/op
BenchmarkMarshal/Go_int64_to_CBOR_negative_int-2 | 91.2 ns/op | 3 B/op | 1 allocs/op
BenchmarkMarshal/Go_float64_to_CBOR_float-2 | 100 ns/op | 16 B/op | 1 allocs/op
BenchmarkMarshal/Go_[]uint8_to_CBOR_bytes-2 | 123 ns/op | 32 B/op | 1 allocs/op
BenchmarkMarshal/Go_string_to_CBOR_text-2 | 118 ns/op | 48 B/op | 1 allocs/op
BenchmarkMarshal/Go_[]int_to_CBOR_array-2 | 528 ns/op | 32 B/op | 1 allocs/op
BenchmarkMarshal/Go_map[string]string_to_CBOR_map-2 | 2096 ns/op | 576 B/op | 28 allocs/op
## Go structs
@ -74,13 +74,13 @@ Benchmarks use struct and map[string]interface{} representing the following valu
Decoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkUnmarshal/CBOR_map_to_Go_map[string]interface{}-2 | 6380 ns/op | 2620 B/op | 73 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_struct-2 | 4603 ns/op | 1173 B/op | 10 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_map[string]interface{}-2 | 6260 ns/op | 2621 B/op | 73 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_struct-2 | 4481 ns/op | 1172 B/op | 10 allocs/op
Encoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkMarshal/Go_map[string]interface{}_to_CBOR_map-2 | 4394 ns/op | 1072 B/op | 45 allocs/op
BenchmarkMarshal/Go_struct_to_CBOR_map-2 | 2770 ns/op | 720 B/op | 28 allocs/op
BenchmarkMarshal/Go_map[string]interface{}_to_CBOR_map-2 | 4462 ns/op | 1072 B/op | 45 allocs/op
BenchmarkMarshal/Go_struct_to_CBOR_map-2 | 2891 ns/op | 720 B/op | 28 allocs/op
## Go structs with "keyasint" struct tag
@ -116,13 +116,13 @@ type T struct {
Decoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkUnmarshal/CBOR_map_to_Go_map[int]interface{}-2| 6222 ns/op | 2516 B/op | 70 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_struct_keyasint-2 | 4782 ns/op | 1237 B/op | 18 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_map[int]interface{}-2| 6070 ns/op | 2517 B/op | 70 allocs/op
BenchmarkUnmarshal/CBOR_map_to_Go_struct_keyasint-2 | 4355 ns/op | 1173 B/op | 10 allocs/op
Encoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkMarshal/Go_map[int]interface{}_to_CBOR_map-2 | 4307 ns/op | 992 B/op | 45 allocs/op
BenchmarkMarshal/Go_struct_keyasint_to_CBOR_map-2 | 2777 ns/op | 704 B/op | 28 allocs/op
BenchmarkMarshal/Go_map[int]interface{}_to_CBOR_map-2 | 4318 ns/op | 992 B/op | 45 allocs/op
BenchmarkMarshal/Go_struct_keyasint_to_CBOR_map-2 | 2879 ns/op | 704 B/op | 28 allocs/op
## Go structs with "toarray" struct tag
@ -159,13 +159,13 @@ type T struct {
Decoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkUnmarshal/CBOR_array_to_Go_[]interface{}-2 | 5010 ns/op | 2404 B/op | 67 allocs/op
BenchmarkUnmarshal/CBOR_array_to_Go_struct_toarray-2 | 4301 ns/op | 1164 B/op | 9 allocs/op
BenchmarkUnmarshal/CBOR_array_to_Go_[]interface{}-2 | 4968 ns/op | 2404 B/op | 67 allocs/op
BenchmarkUnmarshal/CBOR_array_to_Go_struct_toarray-2 | 4205 ns/op | 1164 B/op | 9 allocs/op
Encoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkMarshal/Go_[]interface{}_to_CBOR_map-2 | 3128 ns/op | 704 B/op | 28 allocs/op
BenchmarkMarshal/Go_struct_toarray_to_CBOR_array-2 | 2741 ns/op | 704 B/op | 28 allocs/op
BenchmarkMarshal/Go_[]interface{}_to_CBOR_map-2 | 3272 ns/op | 704 B/op | 28 allocs/op
BenchmarkMarshal/Go_struct_toarray_to_CBOR_array-2 | 2840 ns/op | 704 B/op | 28 allocs/op
## COSE data
@ -205,15 +205,15 @@ Benchmarks use COSE data from https://tools.ietf.org/html/rfc8392#appendix-A sec
Decoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkUnmarshalCOSE/128-Bit_Symmetric_Key-2 | 761 ns/op | 280 B/op | 9 allocs/op
BenchmarkUnmarshalCOSE/256-Bit_Symmetric_Key-2 | 768 ns/op | 296 B/op | 9 allocs/op
BenchmarkUnmarshalCOSE/ECDSA_P256_256-Bit_Key-2 | 1385 ns/op | 448 B/op | 18 allocs/op
BenchmarkUnmarshalCOSE/128-Bit_Symmetric_Key-2 | 578 ns/op | 240 B/op | 4 allocs/op
BenchmarkUnmarshalCOSE/256-Bit_Symmetric_Key-2 | 586 ns/op | 256 B/op | 4 allocs/op
BenchmarkUnmarshalCOSE/ECDSA_P256_256-Bit_Key-2 | 989 ns/op | 360 B/op | 7 allocs/op
Encoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkMarshalCOSE/128-Bit_Symmetric_Key-2 | 510 ns/op | 224 B/op | 2 allocs/op
BenchmarkMarshalCOSE/256-Bit_Symmetric_Key-2 | 512 ns/op | 240 B/op | 2 allocs/op
BenchmarkMarshalCOSE/ECDSA_P256_256-Bit_Key-2 | 674 ns/op | 320 B/op | 2 allocs/op
BenchmarkMarshalCOSE/128-Bit_Symmetric_Key-2 | 535 ns/op | 224 B/op | 2 allocs/op
BenchmarkMarshalCOSE/256-Bit_Symmetric_Key-2 | 543 ns/op | 240 B/op | 2 allocs/op
BenchmarkMarshalCOSE/ECDSA_P256_256-Bit_Key-2 | 681 ns/op | 320 B/op | 2 allocs/op
## CWT claims data
@ -233,11 +233,11 @@ Benchmarks use CTW claims data from https://tools.ietf.org/html/rfc8392#appendix
Decoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkUnmarshalCWTClaims-2 | 1029 ns/op | 240 B/op | 13 allocs/op
BenchmarkUnmarshalCWTClaims-2 | 796 ns/op | 176 B/op | 6 allocs/op
Encoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkMarshalCWTClaims-2 | 445 ns/op | 176 B/op | 2 allocs/op
BenchmarkMarshalCWTClaims-2 | 466 ns/op | 176 B/op | 2 allocs/op
## SenML data
@ -257,8 +257,8 @@ Benchmarks use SenML data from https://tools.ietf.org/html/rfc8428#section-6
Decoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkUnmarshalSenML-2 | 4279 ns/op | 1720 B/op | 40 allocs/op
BenchmarkUnmarshalSenML-2 | 3146 ns/op | 1544 B/op | 18 allocs/op
Encoding Benchmark | Time | Memory | Allocs
--- | ---: | ---: | ---:
BenchmarkMarshalSenML-2 | 2906 ns/op | 272 B/op | 2 allocs/op
BenchmarkMarshalSenML-2 | 2968 ns/op | 272 B/op | 2 allocs/op

View File

@ -645,18 +645,18 @@ For more examples, see [examples_test.go](example_test.go).
Go structs are faster than maps with string keys:
* decoding into struct is >27% faster than decoding into map.
* encoding struct is >36% faster than encoding map.
* decoding into struct is >28% faster than decoding into map.
* encoding struct is >35% faster than encoding map.
Go structs with `keyasint` struct tag are faster than maps with integer keys:
* decoding into struct is >23% faster than decoding into map.
* encoding struct is >35% faster than encoding map.
* decoding into struct is >28% faster than decoding into map.
* encoding struct is >33% faster than encoding map.
Go structs with `toarray` struct tag are faster than slice:
* decoding into struct is >14% faster than decoding into slice.
* encoding struct is >12% faster than encoding slice.
* decoding into struct is >15% faster than decoding into slice.
* encoding struct is >13% faster than encoding slice.
Doing your own benchmarks is highly recommended. Use your most common message sizes and data types.

View File

@ -8,6 +8,7 @@ import (
"encoding/hex"
"fmt"
"io"
"reflect"
"time"
"github.com/fxamacker/cbor/v2"
@ -376,6 +377,31 @@ func Example_cWT() {
// {Iss:coap://as.example.com Sub:erikw Aud:coap://light.example.com Exp:1444064944 Nbf:1443944944 Iat:1443944944 Cti:[11 113]}
}
func Example_cWTWithDupMapKeyOption() {
type claims struct {
Iss string `cbor:"1,keyasint"`
Sub string `cbor:"2,keyasint"`
Aud string `cbor:"3,keyasint"`
Exp int `cbor:"4,keyasint"`
Nbf int `cbor:"5,keyasint"`
Iat int `cbor:"6,keyasint"`
Cti []byte `cbor:"7,keyasint"`
}
// Data from https://tools.ietf.org/html/rfc8392#appendix-A section A.1
cborData, _ := hex.DecodeString("a70175636f61703a2f2f61732e6578616d706c652e636f6d02656572696b77037818636f61703a2f2f6c696768742e6578616d706c652e636f6d041a5612aeb0051a5610d9f0061a5610d9f007420b71")
dm, _ := cbor.DecOptions{DupMapKey: cbor.DupMapKeyEnforcedAPF}.DecMode()
var v claims
if err := dm.Unmarshal(cborData, &v); err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", v)
// Output:
// {Iss:coap://as.example.com Sub:erikw Aud:coap://light.example.com Exp:1444064944 Nbf:1443944944 Iat:1443944944 Cti:[11 113]}
}
func Example_signedCWT() {
// Use "keyasint" struct tag to encode/decode struct to/from CBOR map.
// Partial COSE header definition
@ -406,6 +432,48 @@ func Example_signedCWT() {
// {_:{} Protected:[161 1 38] Unprotected:{Alg:0 Kid:[65 115 121 109 109 101 116 114 105 99 69 67 68 83 65 50 53 54] IV:[]} Payload:[167 1 117 99 111 97 112 58 47 47 97 115 46 101 120 97 109 112 108 101 46 99 111 109 2 101 101 114 105 107 119 3 120 24 99 111 97 112 58 47 47 108 105 103 104 116 46 101 120 97 109 112 108 101 46 99 111 109 4 26 86 18 174 176 5 26 86 16 217 240 6 26 86 16 217 240 7 66 11 113] Signature:[84 39 193 255 40 210 63 186 209 242 156 76 124 106 85 94 96 29 111 162 159 145 121 188 61 116 56 186 202 202 90 205 8 200 212 212 249 97 49 104 12 66 154 1 248 89 81 236 238 116 58 82 185 182 54 50 197 114 9 18 14 28 158 48]}
}
func Example_signedCWTWithTag() {
// Use "keyasint" struct tag to encode/decode struct to/from CBOR map.
// Partial COSE header definition
type coseHeader struct {
Alg int `cbor:"1,keyasint,omitempty"`
Kid []byte `cbor:"4,keyasint,omitempty"`
IV []byte `cbor:"5,keyasint,omitempty"`
}
// Use "toarray" struct tag to encode/decode struct to/from CBOR array.
type signedCWT struct {
_ struct{} `cbor:",toarray"`
Protected []byte
Unprotected coseHeader
Payload []byte
Signature []byte
}
// Data from https://tools.ietf.org/html/rfc8392#appendix-A section A.3
cborData, _ := hex.DecodeString("d28443a10126a104524173796d6d657472696345434453413235365850a70175636f61703a2f2f61732e6578616d706c652e636f6d02656572696b77037818636f61703a2f2f6c696768742e6578616d706c652e636f6d041a5612aeb0051a5610d9f0061a5610d9f007420b7158405427c1ff28d23fbad1f29c4c7c6a555e601d6fa29f9179bc3d7438bacaca5acd08c8d4d4f96131680c429a01f85951ecee743a52b9b63632c57209120e1c9e30")
// Register tag COSE_Sign1 18 with signedCWT type.
tags := cbor.NewTagSet()
if err := tags.Add(cbor.TagOptions{EncTag: cbor.EncTagRequired, DecTag: cbor.DecTagRequired}, reflect.TypeOf(signedCWT{}), 18); err != nil {
fmt.Println("error:", err)
}
dm, _ := cbor.DecOptions{}.DecModeWithTags(tags)
em, _ := cbor.EncOptions{}.EncModeWithTags(tags)
var v signedCWT
if err := dm.Unmarshal(cborData, &v); err != nil {
fmt.Println("error:", err)
}
if _, err := em.Marshal(v); err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", v)
// Output:
// {_:{} Protected:[161 1 38] Unprotected:{Alg:0 Kid:[65 115 121 109 109 101 116 114 105 99 69 67 68 83 65 50 53 54] IV:[]} Payload:[167 1 117 99 111 97 112 58 47 47 97 115 46 101 120 97 109 112 108 101 46 99 111 109 2 101 101 114 105 107 119 3 120 24 99 111 97 112 58 47 47 108 105 103 104 116 46 101 120 97 109 112 108 101 46 99 111 109 4 26 86 18 174 176 5 26 86 16 217 240 6 26 86 16 217 240 7 66 11 113] Signature:[84 39 193 255 40 210 63 186 209 242 156 76 124 106 85 94 96 29 111 162 159 145 121 188 61 116 56 186 202 202 90 205 8 200 212 212 249 97 49 104 12 66 154 1 248 89 81 236 238 116 58 82 185 182 54 50 197 114 9 18 14 28 158 48]}
}
func Example_cOSE() {
// Use "keyasint" struct tag to encode/decode struct to/from CBOR map.
// Use cbor.RawMessage to delay unmarshaling (CrvOrNOrK's data type depends on Kty's value).