You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
6.3 KiB

  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Large data benchmark.
  5. // The JSON data is a summary of agl's changes in the
  6. // go, webkit, and chromium open source projects.
  7. // We benchmark converting between the JSON form
  8. // and in-memory data structures.
  9. package fastjson
  10. import (
  11. "bytes"
  12. "compress/gzip"
  13. "io/ioutil"
  14. "os"
  15. "strings"
  16. "testing"
  17. )
  18. type codeResponse struct {
  19. Tree *codeNode `json:"tree"`
  20. Username string `json:"username"`
  21. }
  22. type codeNode struct {
  23. Name string `json:"name"`
  24. Kids []*codeNode `json:"kids"`
  25. CLWeight float64 `json:"cl_weight"`
  26. Touches int `json:"touches"`
  27. MinT int64 `json:"min_t"`
  28. MaxT int64 `json:"max_t"`
  29. MeanT int64 `json:"mean_t"`
  30. }
  31. var testData [][]byte
  32. var codeJSON []byte
  33. var codeStruct codeResponse
  34. var fileNames = [...]string{"testdata/canada.json.gz",
  35. "testdata/code.json.gz",
  36. "testdata/large-dict.json.gz",
  37. "testdata/medium-dict.json.gz"}
  38. func codeInit() {
  39. f, err := os.Open("testdata/code.json.gz")
  40. if err != nil {
  41. panic(err)
  42. }
  43. defer f.Close()
  44. gz, err := gzip.NewReader(f)
  45. if err != nil {
  46. panic(err)
  47. }
  48. data, err := ioutil.ReadAll(gz)
  49. if err != nil {
  50. panic(err)
  51. }
  52. codeJSON = data
  53. if err := Unmarshal(codeJSON, &codeStruct); err != nil {
  54. panic("unmarshal code.json: " + err.Error())
  55. }
  56. if data, err = Marshal(&codeStruct); err != nil {
  57. panic("marshal code.json: " + err.Error())
  58. }
  59. if !bytes.Equal(data, codeJSON) {
  60. println("different lengths", len(data), len(codeJSON))
  61. for i := 0; i < len(data) && i < len(codeJSON); i++ {
  62. if data[i] != codeJSON[i] {
  63. println("re-marshal: changed at byte", i)
  64. println("orig: ", string(codeJSON[i-10:i+10]))
  65. println("new: ", string(data[i-10:i+10]))
  66. break
  67. }
  68. }
  69. panic("re-marshal code.json: different result")
  70. }
  71. testData = make([][]byte, len(fileNames))
  72. for i, name := range fileNames {
  73. f, err = os.Open(name)
  74. if err != nil {
  75. panic(err)
  76. }
  77. defer f.Close()
  78. gz, err = gzip.NewReader(f)
  79. if err != nil {
  80. panic(err)
  81. }
  82. testData[i], err = ioutil.ReadAll(gz)
  83. if err != nil {
  84. panic(err)
  85. }
  86. var jsonObj interface{}
  87. if err = Unmarshal(testData[i], &jsonObj); err != nil {
  88. panic("unmarshal code.json: " + err.Error())
  89. }
  90. }
  91. }
  92. func BenchmarkCodeEncoder(b *testing.B) {
  93. if codeJSON == nil {
  94. b.StopTimer()
  95. codeInit()
  96. b.StartTimer()
  97. }
  98. enc := NewEncoder(ioutil.Discard)
  99. for i := 0; i < b.N; i++ {
  100. if err := enc.Encode(&codeStruct); err != nil {
  101. b.Fatal("Encode:", err)
  102. }
  103. }
  104. b.SetBytes(int64(len(codeJSON)))
  105. }
  106. func BenchmarkCodeMarshal(b *testing.B) {
  107. if codeJSON == nil {
  108. b.StopTimer()
  109. codeInit()
  110. b.StartTimer()
  111. }
  112. for i := 0; i < b.N; i++ {
  113. if _, err := Marshal(&codeStruct); err != nil {
  114. b.Fatal("Marshal:", err)
  115. }
  116. }
  117. b.SetBytes(int64(len(codeJSON)))
  118. }
  119. func BenchmarkCodeDecoder(b *testing.B) {
  120. if codeJSON == nil {
  121. b.StopTimer()
  122. codeInit()
  123. b.StartTimer()
  124. }
  125. var buf bytes.Buffer
  126. dec := NewDecoder(&buf)
  127. var r codeResponse
  128. for i := 0; i < b.N; i++ {
  129. buf.Write(codeJSON)
  130. // hide EOF
  131. buf.WriteByte('\n')
  132. buf.WriteByte('\n')
  133. buf.WriteByte('\n')
  134. if err := dec.Decode(&r); err != nil {
  135. b.Fatal("Decode:", err)
  136. }
  137. }
  138. b.SetBytes(int64(len(codeJSON)))
  139. }
  140. func BenchmarkDecoderStream(b *testing.B) {
  141. b.StopTimer()
  142. var buf bytes.Buffer
  143. dec := NewDecoder(&buf)
  144. buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n")
  145. var x interface{}
  146. if err := dec.Decode(&x); err != nil {
  147. b.Fatal("Decode:", err)
  148. }
  149. ones := strings.Repeat(" 1\n", 300000) + "\n\n\n"
  150. b.StartTimer()
  151. for i := 0; i < b.N; i++ {
  152. if i%300000 == 0 {
  153. buf.WriteString(ones)
  154. }
  155. x = nil
  156. if err := dec.Decode(&x); err != nil || x != 1.0 {
  157. b.Fatalf("Decode: %v after %d", err, i)
  158. }
  159. }
  160. }
  161. func BenchmarkCodeUnmarshal(b *testing.B) {
  162. if codeJSON == nil {
  163. b.StopTimer()
  164. codeInit()
  165. b.StartTimer()
  166. }
  167. for i := 0; i < b.N; i++ {
  168. var r codeResponse
  169. if err := Unmarshal(codeJSON, &r); err != nil {
  170. b.Fatal("Unmarshal:", err)
  171. }
  172. }
  173. b.SetBytes(int64(len(codeJSON)))
  174. }
  175. func BenchmarkCodeUnmarshalReuse(b *testing.B) {
  176. if codeJSON == nil {
  177. b.StopTimer()
  178. codeInit()
  179. b.StartTimer()
  180. }
  181. var r codeResponse
  182. for i := 0; i < b.N; i++ {
  183. if err := Unmarshal(codeJSON, &r); err != nil {
  184. b.Fatal("Unmarshal:", err)
  185. }
  186. }
  187. }
  188. func BenchmarkCodeUnmarshalManyNumbers(b *testing.B) {
  189. if codeJSON == nil {
  190. b.StopTimer()
  191. codeInit()
  192. b.StartTimer()
  193. }
  194. for i := 0; i < b.N; i++ {
  195. var r interface{}
  196. if err := Unmarshal(testData[0], &r); err != nil {
  197. b.Fatal("Unmarshal:", err)
  198. }
  199. }
  200. b.SetBytes(int64(len(testData[0])))
  201. }
  202. func BenchmarkCodeUnmarshalNoReflect(b *testing.B) {
  203. if codeJSON == nil {
  204. b.StopTimer()
  205. codeInit()
  206. b.StartTimer()
  207. }
  208. for i := 0; i < b.N; i++ {
  209. var r interface{}
  210. if err := Unmarshal(testData[1], &r); err != nil {
  211. b.Fatal("Unmarshal:", err)
  212. }
  213. }
  214. b.SetBytes(int64(len(testData[1])))
  215. }
  216. func BenchmarkCodeUnmarshalLargeFile(b *testing.B) {
  217. if codeJSON == nil {
  218. b.StopTimer()
  219. codeInit()
  220. b.StartTimer()
  221. }
  222. for i := 0; i < b.N; i++ {
  223. var r interface{}
  224. if err := Unmarshal(testData[2], &r); err != nil {
  225. b.Fatal("Unmarshal:", err)
  226. }
  227. }
  228. b.SetBytes(int64(len(testData[2])))
  229. }
  230. func BenchmarkCodeUnmarshalMediumFile(b *testing.B) {
  231. if codeJSON == nil {
  232. b.StopTimer()
  233. codeInit()
  234. b.StartTimer()
  235. }
  236. for i := 0; i < b.N; i++ {
  237. var r interface{}
  238. if err := Unmarshal(testData[3], &r); err != nil {
  239. b.Fatal("Unmarshal:", err)
  240. }
  241. }
  242. b.SetBytes(int64(len(testData[3])))
  243. }
  244. func BenchmarkUnmarshalString(b *testing.B) {
  245. data := []byte(`"hello, world"`)
  246. var s string
  247. for i := 0; i < b.N; i++ {
  248. if err := Unmarshal(data, &s); err != nil {
  249. b.Fatal("Unmarshal:", err)
  250. }
  251. }
  252. }
  253. func BenchmarkUnmarshalFloat64(b *testing.B) {
  254. var f float64
  255. data := []byte(`3.14`)
  256. for i := 0; i < b.N; i++ {
  257. if err := Unmarshal(data, &f); err != nil {
  258. b.Fatal("Unmarshal:", err)
  259. }
  260. }
  261. }
  262. func BenchmarkUnmarshalInt64(b *testing.B) {
  263. var x int64
  264. data := []byte(`3`)
  265. for i := 0; i < b.N; i++ {
  266. if err := Unmarshal(data, &x); err != nil {
  267. b.Fatal("Unmarshal:", err)
  268. }
  269. }
  270. }
  271. func BenchmarkIssue10335(b *testing.B) {
  272. b.ReportAllocs()
  273. var s struct{}
  274. j := []byte(`{"a":{ }}`)
  275. for n := 0; n < b.N; n++ {
  276. if err := Unmarshal(j, &s); err != nil {
  277. b.Fatal(err)
  278. }
  279. }
  280. }