1package mapstructure 2 3import ( 4 "encoding/json" 5 "testing" 6) 7 8type Person struct { 9 Name string 10 Age int 11 Emails []string 12 Extra map[string]string 13} 14 15func Benchmark_Decode(b *testing.B) { 16 input := map[string]interface{}{ 17 "name": "Mitchell", 18 "age": 91, 19 "emails": []string{"one", "two", "three"}, 20 "extra": map[string]string{ 21 "twitter": "mitchellh", 22 }, 23 } 24 25 var result Person 26 for i := 0; i < b.N; i++ { 27 Decode(input, &result) 28 } 29} 30 31// decodeViaJSON takes the map data and passes it through encoding/json to convert it into the 32// given Go native structure pointed to by v. v must be a pointer to a struct. 33func decodeViaJSON(data interface{}, v interface{}) error { 34 // Perform the task by simply marshalling the input into JSON, 35 // then unmarshalling it into target native Go struct. 36 b, err := json.Marshal(data) 37 if err != nil { 38 return err 39 } 40 return json.Unmarshal(b, v) 41} 42 43func Benchmark_DecodeViaJSON(b *testing.B) { 44 input := map[string]interface{}{ 45 "name": "Mitchell", 46 "age": 91, 47 "emails": []string{"one", "two", "three"}, 48 "extra": map[string]string{ 49 "twitter": "mitchellh", 50 }, 51 } 52 53 var result Person 54 for i := 0; i < b.N; i++ { 55 decodeViaJSON(input, &result) 56 } 57} 58 59func Benchmark_JSONUnmarshal(b *testing.B) { 60 input := map[string]interface{}{ 61 "name": "Mitchell", 62 "age": 91, 63 "emails": []string{"one", "two", "three"}, 64 "extra": map[string]string{ 65 "twitter": "mitchellh", 66 }, 67 } 68 69 inputB, err := json.Marshal(input) 70 if err != nil { 71 b.Fatal("Failed to marshal test input:", err) 72 } 73 74 var result Person 75 for i := 0; i < b.N; i++ { 76 json.Unmarshal(inputB, &result) 77 } 78} 79 80func Benchmark_DecodeBasic(b *testing.B) { 81 input := map[string]interface{}{ 82 "vstring": "foo", 83 "vint": 42, 84 "Vuint": 42, 85 "vbool": true, 86 "Vfloat": 42.42, 87 "vsilent": true, 88 "vdata": 42, 89 "vjsonInt": json.Number("1234"), 90 "vjsonFloat": json.Number("1234.5"), 91 "vjsonNumber": json.Number("1234.5"), 92 } 93 94 for i := 0; i < b.N; i++ { 95 var result Basic 96 Decode(input, &result) 97 } 98} 99 100func Benchmark_DecodeEmbedded(b *testing.B) { 101 input := map[string]interface{}{ 102 "vstring": "foo", 103 "Basic": map[string]interface{}{ 104 "vstring": "innerfoo", 105 }, 106 "vunique": "bar", 107 } 108 109 var result Embedded 110 for i := 0; i < b.N; i++ { 111 Decode(input, &result) 112 } 113} 114 115func Benchmark_DecodeTypeConversion(b *testing.B) { 116 input := map[string]interface{}{ 117 "IntToFloat": 42, 118 "IntToUint": 42, 119 "IntToBool": 1, 120 "IntToString": 42, 121 "UintToInt": 42, 122 "UintToFloat": 42, 123 "UintToBool": 42, 124 "UintToString": 42, 125 "BoolToInt": true, 126 "BoolToUint": true, 127 "BoolToFloat": true, 128 "BoolToString": true, 129 "FloatToInt": 42.42, 130 "FloatToUint": 42.42, 131 "FloatToBool": 42.42, 132 "FloatToString": 42.42, 133 "StringToInt": "42", 134 "StringToUint": "42", 135 "StringToBool": "1", 136 "StringToFloat": "42.42", 137 "SliceToMap": []interface{}{}, 138 "MapToSlice": map[string]interface{}{}, 139 } 140 141 var resultStrict TypeConversionResult 142 for i := 0; i < b.N; i++ { 143 Decode(input, &resultStrict) 144 } 145} 146 147func Benchmark_DecodeMap(b *testing.B) { 148 input := map[string]interface{}{ 149 "vfoo": "foo", 150 "vother": map[interface{}]interface{}{ 151 "foo": "foo", 152 "bar": "bar", 153 }, 154 } 155 156 var result Map 157 for i := 0; i < b.N; i++ { 158 Decode(input, &result) 159 } 160} 161 162func Benchmark_DecodeMapOfStruct(b *testing.B) { 163 input := map[string]interface{}{ 164 "value": map[string]interface{}{ 165 "foo": map[string]string{"vstring": "one"}, 166 "bar": map[string]string{"vstring": "two"}, 167 }, 168 } 169 170 var result MapOfStruct 171 for i := 0; i < b.N; i++ { 172 Decode(input, &result) 173 } 174} 175 176func Benchmark_DecodeSlice(b *testing.B) { 177 input := map[string]interface{}{ 178 "vfoo": "foo", 179 "vbar": []string{"foo", "bar", "baz"}, 180 } 181 182 var result Slice 183 for i := 0; i < b.N; i++ { 184 Decode(input, &result) 185 } 186} 187 188func Benchmark_DecodeSliceOfStruct(b *testing.B) { 189 input := map[string]interface{}{ 190 "value": []map[string]interface{}{ 191 {"vstring": "one"}, 192 {"vstring": "two"}, 193 }, 194 } 195 196 var result SliceOfStruct 197 for i := 0; i < b.N; i++ { 198 Decode(input, &result) 199 } 200} 201 202func Benchmark_DecodeWeaklyTypedInput(b *testing.B) { 203 // This input can come from anywhere, but typically comes from 204 // something like decoding JSON, generated by a weakly typed language 205 // such as PHP. 206 input := map[string]interface{}{ 207 "name": 123, // number => string 208 "age": "42", // string => number 209 "emails": map[string]interface{}{}, // empty map => empty array 210 } 211 212 var result Person 213 config := &DecoderConfig{ 214 WeaklyTypedInput: true, 215 Result: &result, 216 } 217 218 decoder, err := NewDecoder(config) 219 if err != nil { 220 panic(err) 221 } 222 223 for i := 0; i < b.N; i++ { 224 decoder.Decode(input) 225 } 226} 227 228func Benchmark_DecodeMetadata(b *testing.B) { 229 input := map[string]interface{}{ 230 "name": "Mitchell", 231 "age": 91, 232 "email": "foo@bar.com", 233 } 234 235 var md Metadata 236 var result Person 237 config := &DecoderConfig{ 238 Metadata: &md, 239 Result: &result, 240 } 241 242 decoder, err := NewDecoder(config) 243 if err != nil { 244 panic(err) 245 } 246 247 for i := 0; i < b.N; i++ { 248 decoder.Decode(input) 249 } 250} 251 252func Benchmark_DecodeMetadataEmbedded(b *testing.B) { 253 input := map[string]interface{}{ 254 "vstring": "foo", 255 "vunique": "bar", 256 } 257 258 var md Metadata 259 var result EmbeddedSquash 260 config := &DecoderConfig{ 261 Metadata: &md, 262 Result: &result, 263 } 264 265 decoder, err := NewDecoder(config) 266 if err != nil { 267 b.Fatalf("err: %s", err) 268 } 269 270 for i := 0; i < b.N; i++ { 271 decoder.Decode(input) 272 } 273} 274 275func Benchmark_DecodeTagged(b *testing.B) { 276 input := map[string]interface{}{ 277 "foo": "bar", 278 "bar": "value", 279 } 280 281 var result Tagged 282 for i := 0; i < b.N; i++ { 283 Decode(input, &result) 284 } 285} 286