benchmark_medium_payload_test.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. Each test should process 2.4kb json record (based on Clearbit API)
  3. It should read multiple nested fields and 1 array
  4. */
  5. package benchmark
  6. import (
  7. "encoding/json"
  8. "testing"
  9. "github.com/Jeffail/gabs"
  10. "github.com/a8m/djson"
  11. "github.com/antonholmquist/jason"
  12. "github.com/bitly/go-simplejson"
  13. "github.com/buger/jsonparser"
  14. jlexer "github.com/mailru/easyjson/jlexer"
  15. "github.com/mreiferson/go-ujson"
  16. "github.com/pquerna/ffjson/ffjson"
  17. "github.com/ugorji/go/codec"
  18. // "fmt"
  19. "bytes"
  20. "errors"
  21. )
  22. /*
  23. github.com/buger/jsonparser
  24. */
  25. func BenchmarkJsonParserMedium(b *testing.B) {
  26. for i := 0; i < b.N; i++ {
  27. jsonparser.Get(mediumFixture, "person", "name", "fullName")
  28. jsonparser.GetInt(mediumFixture, "person", "github", "followers")
  29. jsonparser.Get(mediumFixture, "company")
  30. jsonparser.ArrayEach(mediumFixture, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
  31. jsonparser.Get(value, "url")
  32. nothing()
  33. }, "person", "gravatar", "avatars")
  34. }
  35. }
  36. func BenchmarkJsonParserDeleteMedium(b *testing.B) {
  37. fixture := make([]byte, 0, len(mediumFixture))
  38. b.ResetTimer()
  39. for i := 0; i < b.N; i++ {
  40. fixture = append(fixture[:0], mediumFixture...)
  41. fixture = jsonparser.Delete(fixture, "person", "name", "fullName")
  42. fixture = jsonparser.Delete(fixture, "person", "github", "followers")
  43. fixture = jsonparser.Delete(fixture, "company")
  44. nothing()
  45. }
  46. }
  47. func BenchmarkJsonParserEachKeyManualMedium(b *testing.B) {
  48. paths := [][]string{
  49. []string{"person", "name", "fullName"},
  50. []string{"person", "github", "followers"},
  51. []string{"company"},
  52. []string{"person", "gravatar", "avatars"},
  53. }
  54. for i := 0; i < b.N; i++ {
  55. jsonparser.EachKey(mediumFixture, func(idx int, value []byte, vt jsonparser.ValueType, err error) {
  56. switch idx {
  57. case 0:
  58. // jsonparser.ParseString(value)
  59. case 1:
  60. jsonparser.ParseInt(value)
  61. case 2:
  62. // jsonparser.ParseString(value)
  63. case 3:
  64. jsonparser.ArrayEach(value, func(avalue []byte, dataType jsonparser.ValueType, offset int, err error) {
  65. jsonparser.Get(avalue, "url")
  66. })
  67. }
  68. }, paths...)
  69. }
  70. }
  71. func BenchmarkJsonParserEachKeyStructMedium(b *testing.B) {
  72. paths := [][]string{
  73. []string{"person", "name", "fullName"},
  74. []string{"person", "github", "followers"},
  75. []string{"company"},
  76. []string{"person", "gravatar", "avatars"},
  77. }
  78. for i := 0; i < b.N; i++ {
  79. data := MediumPayload{
  80. Person: &CBPerson{
  81. Name: &CBName{},
  82. Github: &CBGithub{},
  83. Gravatar: &CBGravatar{},
  84. },
  85. }
  86. jsonparser.EachKey(mediumFixture, func(idx int, value []byte, vt jsonparser.ValueType, err error) {
  87. switch idx {
  88. case 0:
  89. data.Person.Name.FullName, _ = jsonparser.ParseString(value)
  90. case 1:
  91. v, _ := jsonparser.ParseInt(value)
  92. data.Person.Github.Followers = int(v)
  93. case 2:
  94. json.Unmarshal(value, &data.Company) // we don't have a JSON -> map[string]interface{} function yet, so use standard encoding/json here
  95. case 3:
  96. var avatars []*CBAvatar
  97. jsonparser.ArrayEach(value, func(avalue []byte, dataType jsonparser.ValueType, offset int, err error) {
  98. url, _ := jsonparser.ParseString(avalue)
  99. avatars = append(avatars, &CBAvatar{Url: url})
  100. })
  101. data.Person.Gravatar.Avatars = avatars
  102. }
  103. }, paths...)
  104. }
  105. }
  106. func BenchmarkJsonParserObjectEachStructMedium(b *testing.B) {
  107. nameKey, githubKey, gravatarKey := []byte("name"), []byte("github"), []byte("gravatar")
  108. errStop := errors.New("stop")
  109. for i := 0; i < b.N; i++ {
  110. data := MediumPayload{
  111. Person: &CBPerson{
  112. Name: &CBName{},
  113. Github: &CBGithub{},
  114. Gravatar: &CBGravatar{},
  115. },
  116. }
  117. missing := 3
  118. jsonparser.ObjectEach(mediumFixture, func(k, v []byte, vt jsonparser.ValueType, o int) error {
  119. switch {
  120. case bytes.Equal(k, nameKey):
  121. data.Person.Name.FullName, _ = jsonparser.GetString(v, "fullName")
  122. missing--
  123. case bytes.Equal(k, githubKey):
  124. x, _ := jsonparser.GetInt(v, "followers")
  125. data.Person.Github.Followers = int(x)
  126. missing--
  127. case bytes.Equal(k, gravatarKey):
  128. var avatars []*CBAvatar
  129. jsonparser.ArrayEach(v, func(avalue []byte, dataType jsonparser.ValueType, offset int, err error) {
  130. url, _ := jsonparser.ParseString(avalue)
  131. avatars = append(avatars, &CBAvatar{Url: url})
  132. }, "avatars")
  133. data.Person.Gravatar.Avatars = avatars
  134. missing--
  135. }
  136. if missing == 0 {
  137. return errStop
  138. } else {
  139. return nil
  140. }
  141. }, "person")
  142. cv, _, _, _ := jsonparser.Get(mediumFixture, "company")
  143. json.Unmarshal(cv, &data.Company)
  144. }
  145. }
  146. /*
  147. encoding/json
  148. */
  149. func BenchmarkEncodingJsonStructMedium(b *testing.B) {
  150. for i := 0; i < b.N; i++ {
  151. var data MediumPayload
  152. json.Unmarshal(mediumFixture, &data)
  153. nothing(data.Person.Name.FullName, data.Person.Github.Followers, data.Company)
  154. for _, el := range data.Person.Gravatar.Avatars {
  155. nothing(el.Url)
  156. }
  157. }
  158. }
  159. func BenchmarkEncodingJsonInterfaceMedium(b *testing.B) {
  160. for i := 0; i < b.N; i++ {
  161. var data interface{}
  162. json.Unmarshal(mediumFixture, &data)
  163. m := data.(map[string]interface{})
  164. person := m["person"].(map[string]interface{})
  165. name := person["name"].(map[string]interface{})
  166. github := person["github"].(map[string]interface{})
  167. company := m["company"]
  168. gravatar := person["gravatar"].(map[string]interface{})
  169. avatars := gravatar["avatars"].([]interface{})
  170. nothing(name["fullName"].(string), github["followers"].(float64), company)
  171. for _, a := range avatars {
  172. nothing(a.(map[string]interface{})["url"])
  173. }
  174. }
  175. }
  176. /*
  177. github.com/Jeffail/gabs
  178. */
  179. func BenchmarkGabsMedium(b *testing.B) {
  180. for i := 0; i < b.N; i++ {
  181. json, _ := gabs.ParseJSON(mediumFixture)
  182. person := json.Path("person")
  183. nothing(
  184. person.Path("name.fullName").Data().(string),
  185. person.Path("github.followers").Data().(float64),
  186. )
  187. json.Path("company").ChildrenMap()
  188. arr, _ := person.Path("gravatar.avatars.url").Children()
  189. for _, el := range arr {
  190. nothing(el.String())
  191. }
  192. }
  193. }
  194. /*
  195. github.com/bitly/go-simplejson
  196. */
  197. func BenchmarkGoSimpleJsonMedium(b *testing.B) {
  198. for i := 0; i < b.N; i++ {
  199. json, _ := simplejson.NewJson(mediumFixture)
  200. person := json.Get("person")
  201. person.Get("name").Get("fullName").String()
  202. person.Get("github").Get("followers").Float64()
  203. json.Get("company")
  204. arr, _ := person.Get("gravatar").Get("avatars").Array()
  205. for _, el := range arr {
  206. nothing(el.(map[string]interface{})["url"])
  207. }
  208. }
  209. }
  210. /*
  211. github.com/pquerna/ffjson
  212. */
  213. func BenchmarkFFJsonMedium(b *testing.B) {
  214. for i := 0; i < b.N; i++ {
  215. var data MediumPayload
  216. ffjson.Unmarshal(mediumFixture, &data)
  217. nothing(data.Person.Name.FullName, data.Person.Github.Followers, data.Company)
  218. for _, el := range data.Person.Gravatar.Avatars {
  219. nothing(el.Url)
  220. }
  221. }
  222. }
  223. /*
  224. github.com/bitly/go-simplejson
  225. */
  226. func BenchmarkJasonMedium(b *testing.B) {
  227. for i := 0; i < b.N; i++ {
  228. json, _ := jason.NewObjectFromBytes(mediumFixture)
  229. json.GetString("person.name.fullName")
  230. json.GetFloat64("person.github.followers")
  231. json.GetObject("company")
  232. arr, _ := json.GetObjectArray("person.gravatar.avatars")
  233. for _, el := range arr {
  234. el.GetString("url")
  235. }
  236. nothing()
  237. }
  238. }
  239. /*
  240. github.com/mreiferson/go-ujson
  241. */
  242. func BenchmarkUjsonMedium(b *testing.B) {
  243. for i := 0; i < b.N; i++ {
  244. json, _ := ujson.NewFromBytes(mediumFixture)
  245. person := json.Get("person")
  246. person.Get("name").Get("fullName").String()
  247. person.Get("github").Get("followers").Float64()
  248. json.Get("company").String()
  249. arr := person.Get("gravatar").Get("avatars").Array()
  250. for _, el := range arr {
  251. el.Get("url").String()
  252. }
  253. nothing()
  254. }
  255. }
  256. /*
  257. github.com/a8m/djson
  258. */
  259. func BenchmarkDjsonMedium(b *testing.B) {
  260. for i := 0; i < b.N; i++ {
  261. m, _ := djson.DecodeObject(mediumFixture)
  262. person := m["person"].(map[string]interface{})
  263. name := person["name"].(map[string]interface{})
  264. github := person["github"].(map[string]interface{})
  265. company := m["company"]
  266. gravatar := person["gravatar"].(map[string]interface{})
  267. avatars := gravatar["avatars"].([]interface{})
  268. nothing(name["fullName"].(string), github["followers"].(float64), company)
  269. for _, a := range avatars {
  270. nothing(a.(map[string]interface{})["url"])
  271. }
  272. }
  273. }
  274. /*
  275. github.com/ugorji/go/codec
  276. */
  277. func BenchmarkUgirjiMedium(b *testing.B) {
  278. for i := 0; i < b.N; i++ {
  279. decoder := codec.NewDecoderBytes(mediumFixture, new(codec.JsonHandle))
  280. data := new(MediumPayload)
  281. json.Unmarshal(mediumFixture, &data)
  282. data.CodecDecodeSelf(decoder)
  283. nothing(data.Person.Name.FullName, data.Person.Github.Followers, data.Company)
  284. for _, el := range data.Person.Gravatar.Avatars {
  285. nothing(el.Url)
  286. }
  287. }
  288. }
  289. /*
  290. github.com/mailru/easyjson
  291. */
  292. func BenchmarkEasyJsonMedium(b *testing.B) {
  293. for i := 0; i < b.N; i++ {
  294. lexer := &jlexer.Lexer{Data: mediumFixture}
  295. data := new(MediumPayload)
  296. data.UnmarshalEasyJSON(lexer)
  297. nothing(data.Person.Name.FullName, data.Person.Github.Followers, data.Company)
  298. for _, el := range data.Person.Gravatar.Avatars {
  299. nothing(el.Url)
  300. }
  301. }
  302. }