mapstructure_benchmark_test.go 5.6 KB

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