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