diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-12-12 23:40:51 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-12-12 23:40:51 +0000 |
commit | ab61e9c4da707f3bc7b177c0c8f92daccdb142dc (patch) | |
tree | 0c68629fac9d7c6f103b401c9063ef00ed259f06 /libgo/go/encoding | |
parent | 6e456f4cf4deee3e2ccd9849286f59b90644c48b (diff) | |
download | gcc-ab61e9c4da707f3bc7b177c0c8f92daccdb142dc.zip gcc-ab61e9c4da707f3bc7b177c0c8f92daccdb142dc.tar.gz gcc-ab61e9c4da707f3bc7b177c0c8f92daccdb142dc.tar.bz2 |
libgo: Update to weekly.2011-11-18.
From-SVN: r182266
Diffstat (limited to 'libgo/go/encoding')
-rw-r--r-- | libgo/go/encoding/json/bench_test.go | 157 | ||||
-rw-r--r-- | libgo/go/encoding/json/decode.go | 6 | ||||
-rw-r--r-- | libgo/go/encoding/json/scanner.go | 19 | ||||
-rw-r--r-- | libgo/go/encoding/json/scanner_test.go | 5 | ||||
-rw-r--r-- | libgo/go/encoding/xml/xml_test.go | 17 |
5 files changed, 188 insertions, 16 deletions
diff --git a/libgo/go/encoding/json/bench_test.go b/libgo/go/encoding/json/bench_test.go new file mode 100644 index 0000000..f0c5201 --- /dev/null +++ b/libgo/go/encoding/json/bench_test.go @@ -0,0 +1,157 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Large data benchmark. +// The JSON data is a summary of agl's changes in the +// go, webkit, and chromium open source projects. +// We benchmark converting between the JSON form +// and in-memory data structures. + +package json + +import ( + "bytes" + "compress/gzip" + "io/ioutil" + "os" + "testing" +) + +type codeResponse struct { + Tree *codeNode `json:"tree"` + Username string `json:"username"` +} + +type codeNode struct { + Name string `json:"name"` + Kids []*codeNode `json:"kids"` + CLWeight float64 `json:"cl_weight"` + Touches int `json:"touches"` + MinT int64 `json:"min_t"` + MaxT int64 `json:"max_t"` + MeanT int64 `json:"mean_t"` +} + +var codeJSON []byte +var codeStruct codeResponse + +func codeInit() { + f, err := os.Open("testdata/code.json.gz") + if err != nil { + panic(err) + } + defer f.Close() + gz, err := gzip.NewReader(f) + if err != nil { + panic(err) + } + data, err := ioutil.ReadAll(gz) + if err != nil { + panic(err) + } + + codeJSON = data + + if err := Unmarshal(codeJSON, &codeStruct); err != nil { + panic("unmarshal code.json: " + err.Error()) + } + + if data, err = Marshal(&codeStruct); err != nil { + panic("marshal code.json: " + err.Error()) + } + + if !bytes.Equal(data, codeJSON) { + println("different lengths", len(data), len(codeJSON)) + for i := 0; i < len(data) && i < len(codeJSON); i++ { + if data[i] != codeJSON[i] { + println("re-marshal: changed at byte", i) + println("orig: ", string(codeJSON[i-10:i+10])) + println("new: ", string(data[i-10:i+10])) + break + } + } + panic("re-marshal code.json: different result") + } +} + +func BenchmarkCodeEncoder(b *testing.B) { + if codeJSON == nil { + b.StopTimer() + codeInit() + b.StartTimer() + } + enc := NewEncoder(ioutil.Discard) + for i := 0; i < b.N; i++ { + if err := enc.Encode(&codeStruct); err != nil { + panic(err) + } + } + b.SetBytes(int64(len(codeJSON))) +} + +func BenchmarkCodeMarshal(b *testing.B) { + if codeJSON == nil { + b.StopTimer() + codeInit() + b.StartTimer() + } + for i := 0; i < b.N; i++ { + if _, err := Marshal(&codeStruct); err != nil { + panic(err) + } + } + b.SetBytes(int64(len(codeJSON))) +} + +func BenchmarkCodeDecoder(b *testing.B) { + if codeJSON == nil { + b.StopTimer() + codeInit() + b.StartTimer() + } + var buf bytes.Buffer + dec := NewDecoder(&buf) + var r codeResponse + for i := 0; i < b.N; i++ { + buf.Write(codeJSON) + // hide EOF + buf.WriteByte('\n') + buf.WriteByte('\n') + buf.WriteByte('\n') + if err := dec.Decode(&r); err != nil { + panic(err) + } + } + b.SetBytes(int64(len(codeJSON))) +} + +func BenchmarkCodeUnmarshal(b *testing.B) { + if codeJSON == nil { + b.StopTimer() + codeInit() + b.StartTimer() + } + for i := 0; i < b.N; i++ { + var r codeResponse + if err := Unmarshal(codeJSON, &r); err != nil { + panic(err) + } + } + b.SetBytes(int64(len(codeJSON))) +} + +func BenchmarkCodeUnmarshalReuse(b *testing.B) { + if codeJSON == nil { + b.StopTimer() + codeInit() + b.StartTimer() + } + var r codeResponse + for i := 0; i < b.N; i++ { + if err := Unmarshal(codeJSON, &r); err != nil { + panic(err) + } + } + b.SetBytes(int64(len(codeJSON))) +} diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go index 41295d2..2ea06c5 100644 --- a/libgo/go/encoding/json/decode.go +++ b/libgo/go/encoding/json/decode.go @@ -227,7 +227,7 @@ func (d *decodeState) value(v reflect.Value) { // d.scan thinks we're still at the beginning of the item. // Feed in an empty string - the shortest, simplest value - // so that it knows we got to the end of the value. - if d.scan.step == stateRedo { + if d.scan.redo { panic("redo") } d.scan.step(&d.scan, '"') @@ -381,6 +381,7 @@ func (d *decodeState) array(v reflect.Value) { d.error(errPhase) } } + if i < av.Len() { if !sv.IsValid() { // Array. Zero the rest. @@ -392,6 +393,9 @@ func (d *decodeState) array(v reflect.Value) { sv.SetLen(i) } } + if i == 0 && av.Kind() == reflect.Slice && sv.IsNil() { + sv.Set(reflect.MakeSlice(sv.Type(), 0, 0)) + } } // object consumes an object from d.data[d.off-1:], decoding into the value v. diff --git a/libgo/go/encoding/json/scanner.go b/libgo/go/encoding/json/scanner.go index 1796904..2661f41 100644 --- a/libgo/go/encoding/json/scanner.go +++ b/libgo/go/encoding/json/scanner.go @@ -80,6 +80,9 @@ type scanner struct { // on a 64-bit Mac Mini, and it's nicer to read. step func(*scanner, int) int + // Reached end of top-level value. + endTop bool + // Stack of what we're in the middle of - array values, object keys, object values. parseState []int @@ -87,6 +90,7 @@ type scanner struct { err error // 1-byte redo (see undo method) + redo bool redoCode int redoState func(*scanner, int) int @@ -135,6 +139,8 @@ func (s *scanner) reset() { s.step = stateBeginValue s.parseState = s.parseState[0:0] s.err = nil + s.redo = false + s.endTop = false } // eof tells the scanner that the end of input has been reached. @@ -143,11 +149,11 @@ func (s *scanner) eof() int { if s.err != nil { return scanError } - if s.step == stateEndTop { + if s.endTop { return scanEnd } s.step(s, ' ') - if s.step == stateEndTop { + if s.endTop { return scanEnd } if s.err == nil { @@ -166,8 +172,10 @@ func (s *scanner) pushParseState(p int) { func (s *scanner) popParseState() { n := len(s.parseState) - 1 s.parseState = s.parseState[0:n] + s.redo = false if n == 0 { s.step = stateEndTop + s.endTop = true } else { s.step = stateEndValue } @@ -269,6 +277,7 @@ func stateEndValue(s *scanner, c int) int { if n == 0 { // Completed top-level before the current byte. s.step = stateEndTop + s.endTop = true return stateEndTop(s, c) } if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') { @@ -606,16 +615,18 @@ func quoteChar(c int) string { // undo causes the scanner to return scanCode from the next state transition. // This gives callers a simple 1-byte undo mechanism. func (s *scanner) undo(scanCode int) { - if s.step == stateRedo { - panic("invalid use of scanner") + if s.redo { + panic("json: invalid use of scanner") } s.redoCode = scanCode s.redoState = s.step s.step = stateRedo + s.redo = true } // stateRedo helps implement the scanner's 1-byte undo. func stateRedo(s *scanner, c int) int { + s.redo = false s.step = s.redoState return s.redoCode } diff --git a/libgo/go/encoding/json/scanner_test.go b/libgo/go/encoding/json/scanner_test.go index a0a5995..14d8508 100644 --- a/libgo/go/encoding/json/scanner_test.go +++ b/libgo/go/encoding/json/scanner_test.go @@ -186,11 +186,12 @@ func TestNextValueBig(t *testing.T) { } } +var benchScan scanner + func BenchmarkSkipValue(b *testing.B) { initBig() - var scan scanner for i := 0; i < b.N; i++ { - nextValue(jsonBig, &scan) + nextValue(jsonBig, &benchScan) } b.SetBytes(int64(len(jsonBig))) } diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go index 6c874fa..bcb22af 100644 --- a/libgo/go/encoding/xml/xml_test.go +++ b/libgo/go/encoding/xml/xml_test.go @@ -7,7 +7,6 @@ package xml import ( "bytes" "io" - "os" "reflect" "strings" "testing" @@ -43,17 +42,17 @@ var rawTokens = []Token{ CharData([]byte("World <>'\" 白鵬翔")), EndElement{Name{"", "hello"}}, CharData([]byte("\n ")), - StartElement{Name{"", "goodbye"}, nil}, + StartElement{Name{"", "goodbye"}, []Attr{}}, EndElement{Name{"", "goodbye"}}, CharData([]byte("\n ")), StartElement{Name{"", "outer"}, []Attr{{Name{"foo", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}}, CharData([]byte("\n ")), - StartElement{Name{"", "inner"}, nil}, + StartElement{Name{"", "inner"}, []Attr{}}, EndElement{Name{"", "inner"}}, CharData([]byte("\n ")), EndElement{Name{"", "outer"}}, CharData([]byte("\n ")), - StartElement{Name{"tag", "name"}, nil}, + StartElement{Name{"tag", "name"}, []Attr{}}, CharData([]byte("\n ")), CharData([]byte("Some text here.")), CharData([]byte("\n ")), @@ -77,17 +76,17 @@ var cookedTokens = []Token{ CharData([]byte("World <>'\" 白鵬翔")), EndElement{Name{"ns2", "hello"}}, CharData([]byte("\n ")), - StartElement{Name{"ns2", "goodbye"}, nil}, + StartElement{Name{"ns2", "goodbye"}, []Attr{}}, EndElement{Name{"ns2", "goodbye"}}, CharData([]byte("\n ")), StartElement{Name{"ns2", "outer"}, []Attr{{Name{"ns1", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}}, CharData([]byte("\n ")), - StartElement{Name{"ns2", "inner"}, nil}, + StartElement{Name{"ns2", "inner"}, []Attr{}}, EndElement{Name{"ns2", "inner"}}, CharData([]byte("\n ")), EndElement{Name{"ns2", "outer"}}, CharData([]byte("\n ")), - StartElement{Name{"ns3", "name"}, nil}, + StartElement{Name{"ns3", "name"}, []Attr{}}, CharData([]byte("\n ")), CharData([]byte("Some text here.")), CharData([]byte("\n ")), @@ -105,7 +104,7 @@ var rawTokensAltEncoding = []Token{ CharData([]byte("\n")), ProcInst{"xml", []byte(`version="1.0" encoding="x-testing-uppercase"`)}, CharData([]byte("\n")), - StartElement{Name{"", "tag"}, nil}, + StartElement{Name{"", "tag"}, []Attr{}}, CharData([]byte("value")), EndElement{Name{"", "tag"}}, } @@ -205,7 +204,7 @@ func (d *downCaser) ReadByte() (c byte, err error) { func (d *downCaser) Read(p []byte) (int, error) { d.t.Fatalf("unexpected Read call on downCaser reader") - return 0, os.EINVAL + panic("unreachable") } func TestRawTokenAltEncoding(t *testing.T) { |