Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(903)

Delta Between Two Patch Sets: src/pkg/encoding/json/encode.go

Issue 9129044: code review 9129044: encoding/json: faster encoding (Closed)
Left Patch Set: diff -r d881cb1ffc14 https://go.googlecode.com/hg/ Created 10 years, 7 months ago
Right Patch Set: diff -r 07295f40fe71 https://go.googlecode.com/hg/ Created 10 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/encoding/json/decode_test.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2010 The Go Authors. All rights reserved. 1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Package json implements encoding and decoding of JSON objects as defined in 5 // Package json implements encoding and decoding of JSON objects as defined in
6 // RFC 4627. The mapping between JSON objects and Go values is described 6 // RFC 4627. The mapping between JSON objects and Go values is described
7 // in the documentation for the Marshal and Unmarshal functions. 7 // in the documentation for the Marshal and Unmarshal functions.
8 // 8 //
9 // See "JSON and Go" for an introduction to this package: 9 // See "JSON and Go" for an introduction to this package:
10 // http://golang.org/doc/articles/json_and_go.html 10 // http://golang.org/doc/articles/json_and_go.html
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 var wg sync.WaitGroup 338 var wg sync.WaitGroup
339 wg.Add(1) 339 wg.Add(1)
340 encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) { 340 encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) {
341 wg.Wait() 341 wg.Wait()
342 f(e, v, quoted) 342 f(e, v, quoted)
343 } 343 }
344 encoderCache.Unlock() 344 encoderCache.Unlock()
345 345
346 // Compute fields without lock. 346 // Compute fields without lock.
347 // Might duplicate effort but won't hold other computations back. 347 // Might duplicate effort but won't hold other computations back.
348 » f = buildTypeEncoder(t, vx) 348 » f = newTypeEncoder(t, vx)
349 wg.Done() 349 wg.Done()
350 encoderCache.Lock() 350 encoderCache.Lock()
351 encoderCache.m[t] = f 351 encoderCache.m[t] = f
352 encoderCache.Unlock() 352 encoderCache.Unlock()
353 return f 353 return f
354 } 354 }
355 355
356 // buildTypeEncoder constructs an encoderFunc for a type. 356 // newTypeEncoder constructs an encoderFunc for a type.
rsc 2013/08/09 02:04:13 s/build/new/ throughout
357 // The provided vx is an example value of type t. It's the first seen 357 // The provided vx is an example value of type t. It's the first seen
358 // value of that type and should not be used to encode. It may be 358 // value of that type and should not be used to encode. It may be
359 // zero. 359 // zero.
360 func buildTypeEncoder(t reflect.Type, vx reflect.Value) encoderFunc { 360 func newTypeEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
361 if !vx.IsValid() { 361 if !vx.IsValid() {
362 vx = reflect.New(t).Elem() 362 vx = reflect.New(t).Elem()
363 } 363 }
364 _, ok := vx.Interface().(Marshaler) 364 _, ok := vx.Interface().(Marshaler)
365 if ok { 365 if ok {
366 return valueIsMarshallerEncoder 366 return valueIsMarshallerEncoder
367 } 367 }
368 // T doesn't match the interface. Check against *T too. 368 // T doesn't match the interface. Check against *T too.
369 if vx.Kind() != reflect.Ptr && vx.CanAddr() { 369 if vx.Kind() != reflect.Ptr && vx.CanAddr() {
370 _, ok = vx.Addr().Interface().(Marshaler) 370 _, ok = vx.Addr().Interface().(Marshaler)
(...skipping 10 matching lines...) Expand all
381 return uintEncoder 381 return uintEncoder
382 case reflect.Float32: 382 case reflect.Float32:
383 return float32Encoder 383 return float32Encoder
384 case reflect.Float64: 384 case reflect.Float64:
385 return float64Encoder 385 return float64Encoder
386 case reflect.String: 386 case reflect.String:
387 return stringEncoder 387 return stringEncoder
388 case reflect.Interface: 388 case reflect.Interface:
389 return interfaceEncoder 389 return interfaceEncoder
390 case reflect.Struct: 390 case reflect.Struct:
391 » » return buildStructEncoder(t, vx) 391 » » return newStructEncoder(t, vx)
392 case reflect.Map: 392 case reflect.Map:
393 » » return buildMapEncoder(t, vx) 393 » » return newMapEncoder(t, vx)
394 case reflect.Slice: 394 case reflect.Slice:
395 » » return buildSliceEncoder(t, vx) 395 » » return newSliceEncoder(t, vx)
396 case reflect.Array: 396 case reflect.Array:
397 » » return buildArrayEncoder(t, vx) 397 » » return newArrayEncoder(t, vx)
398 case reflect.Ptr: 398 case reflect.Ptr:
399 » » return buildPtrEncoder(t, vx) 399 » » return newPtrEncoder(t, vx)
400 default: 400 default:
401 return unsupportedTypeEncoder 401 return unsupportedTypeEncoder
402 } 402 }
403 } 403 }
404 404
405 func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) { 405 func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) {
406 e.WriteString("null") 406 e.WriteString("null")
407 } 407 }
408 408
409 func valueIsMarshallerEncoder(e *encodeState, v reflect.Value, quoted bool) { 409 func valueIsMarshallerEncoder(e *encodeState, v reflect.Value, quoted bool) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 return 523 return
524 } 524 }
525 e.reflectValue(v.Elem()) 525 e.reflectValue(v.Elem())
526 } 526 }
527 527
528 func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) { 528 func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) {
529 e.error(&UnsupportedTypeError{v.Type()}) 529 e.error(&UnsupportedTypeError{v.Type()})
530 } 530 }
531 531
532 type structEncoder struct { 532 type structEncoder struct {
533 » fields []field 533 » fields []field
534 » fieldFuncs []encoderFunc 534 » fieldEncs []encoderFunc
rsc 2013/08/09 02:04:13 fieldEncs (match all the elemEnc)
535 } 535 }
536 536
537 func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) { 537 func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
538 e.WriteByte('{') 538 e.WriteByte('{')
539 first := true 539 first := true
540 for i, f := range se.fields { 540 for i, f := range se.fields {
541 fv := fieldByIndex(v, f.index) 541 fv := fieldByIndex(v, f.index)
542 if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) { 542 if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
543 continue 543 continue
544 } 544 }
545 if first { 545 if first {
546 first = false 546 first = false
547 } else { 547 } else {
548 e.WriteByte(',') 548 e.WriteByte(',')
549 } 549 }
550 e.string(f.name) 550 e.string(f.name)
551 e.WriteByte(':') 551 e.WriteByte(':')
552 » » if tenc := se.fieldFuncs[i]; tenc != nil { 552 » » if tenc := se.fieldEncs[i]; tenc != nil {
553 tenc(e, fv, f.quoted) 553 tenc(e, fv, f.quoted)
554 } else { 554 } else {
555 // Slower path. 555 // Slower path.
556 e.reflectValue(fv) 556 e.reflectValue(fv)
557 } 557 }
558 } 558 }
559 e.WriteByte('}') 559 e.WriteByte('}')
560 } 560 }
561 561
562 func buildStructEncoder(t reflect.Type, vx reflect.Value) encoderFunc { 562 func newStructEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
563 fields := cachedTypeFields(t) 563 fields := cachedTypeFields(t)
564 se := &structEncoder{ 564 se := &structEncoder{
565 » » fields: fields, 565 » » fields: fields,
566 » » fieldFuncs: make([]encoderFunc, len(fields)), 566 » » fieldEncs: make([]encoderFunc, len(fields)),
567 } 567 }
568 for i, f := range fields { 568 for i, f := range fields {
569 vxf := fieldByIndex(vx, f.index) 569 vxf := fieldByIndex(vx, f.index)
570 if vxf.IsValid() { 570 if vxf.IsValid() {
571 » » » se.fieldFuncs[i] = typeEncoder(vxf.Type(), vxf) 571 » » » se.fieldEncs[i] = typeEncoder(vxf.Type(), vxf)
572 } 572 }
573 } 573 }
574 return se.encode 574 return se.encode
575 } 575 }
576 576
577 type mapEncoder struct { 577 type mapEncoder struct {
578 elemEnc encoderFunc 578 elemEnc encoderFunc
579 } 579 }
580 580
581 func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) { 581 func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
582 if v.IsNil() { 582 if v.IsNil() {
583 e.WriteString("null") 583 e.WriteString("null")
584 return 584 return
585 } 585 }
586 e.WriteByte('{') 586 e.WriteByte('{')
587 var sv stringValues = v.MapKeys() 587 var sv stringValues = v.MapKeys()
588 sort.Sort(sv) 588 sort.Sort(sv)
589 for i, k := range sv { 589 for i, k := range sv {
590 if i > 0 { 590 if i > 0 {
591 e.WriteByte(',') 591 e.WriteByte(',')
592 } 592 }
593 e.string(k.String()) 593 e.string(k.String())
594 e.WriteByte(':') 594 e.WriteByte(':')
595 me.elemEnc(e, v.MapIndex(k), false) 595 me.elemEnc(e, v.MapIndex(k), false)
596 } 596 }
597 e.WriteByte('}') 597 e.WriteByte('}')
598 } 598 }
599 599
600 func buildMapEncoder(t reflect.Type, vx reflect.Value) encoderFunc { 600 func newMapEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
601 if t.Key().Kind() != reflect.String { 601 if t.Key().Kind() != reflect.String {
602 return unsupportedTypeEncoder 602 return unsupportedTypeEncoder
603 } 603 }
604 me := &mapEncoder{typeEncoder(vx.Type().Elem(), reflect.Value{})} 604 me := &mapEncoder{typeEncoder(vx.Type().Elem(), reflect.Value{})}
605 return me.encode 605 return me.encode
606 } 606 }
607 607
608 func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) { 608 func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) {
609 if v.IsNil() { 609 if v.IsNil() {
610 e.WriteString("null") 610 e.WriteString("null")
(...skipping 11 matching lines...) Expand all
622 // buffer space. 622 // buffer space.
623 enc := base64.NewEncoder(base64.StdEncoding, e) 623 enc := base64.NewEncoder(base64.StdEncoding, e)
624 enc.Write(s) 624 enc.Write(s)
625 enc.Close() 625 enc.Close()
626 } 626 }
627 e.WriteByte('"') 627 e.WriteByte('"')
628 } 628 }
629 629
630 // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn' t nil. 630 // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn' t nil.
631 type sliceEncoder struct { 631 type sliceEncoder struct {
632 » arrayEncoder encoderFunc 632 » arrayEnc encoderFunc
rsc 2013/08/09 02:04:13 arrayEnc
633 } 633 }
634 634
635 func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) { 635 func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
636 if v.IsNil() { 636 if v.IsNil() {
637 e.WriteString("null") 637 e.WriteString("null")
638 return 638 return
639 } 639 }
640 » se.arrayEncoder(e, v, false) 640 » se.arrayEnc(e, v, false)
641 } 641 }
642 642
643 func buildSliceEncoder(t reflect.Type, vx reflect.Value) encoderFunc { 643 func newSliceEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
644 // Byte slices get special treatment; arrays don't. 644 // Byte slices get special treatment; arrays don't.
645 if vx.Type().Elem().Kind() == reflect.Uint8 { 645 if vx.Type().Elem().Kind() == reflect.Uint8 {
646 return encodeByteSlice 646 return encodeByteSlice
647 } 647 }
648 » enc := &sliceEncoder{buildArrayEncoder(t, vx)} 648 » enc := &sliceEncoder{newArrayEncoder(t, vx)}
649 return enc.encode 649 return enc.encode
650 } 650 }
651 651
652 type arrayEncoder struct { 652 type arrayEncoder struct {
653 elemEnc encoderFunc 653 elemEnc encoderFunc
654 } 654 }
655 655
656 func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) { 656 func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
657 e.WriteByte('[') 657 e.WriteByte('[')
658 n := v.Len() 658 n := v.Len()
659 for i := 0; i < n; i++ { 659 for i := 0; i < n; i++ {
660 if i > 0 { 660 if i > 0 {
661 e.WriteByte(',') 661 e.WriteByte(',')
662 } 662 }
663 ae.elemEnc(e, v.Index(i), false) 663 ae.elemEnc(e, v.Index(i), false)
664 } 664 }
665 e.WriteByte(']') 665 e.WriteByte(']')
666 } 666 }
667 667
668 func buildArrayEncoder(t reflect.Type, vx reflect.Value) encoderFunc { 668 func newArrayEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
669 enc := &arrayEncoder{typeEncoder(t.Elem(), reflect.Value{})} 669 enc := &arrayEncoder{typeEncoder(t.Elem(), reflect.Value{})}
670 return enc.encode 670 return enc.encode
671 } 671 }
672 672
673 type ptrEncoder struct { 673 type ptrEncoder struct {
674 elemEnc encoderFunc 674 elemEnc encoderFunc
675 } 675 }
676 676
677 func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) { 677 func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
678 if v.IsNil() { 678 if v.IsNil() {
679 e.WriteString("null") 679 e.WriteString("null")
680 return 680 return
681 } 681 }
682 pe.elemEnc(e, v.Elem(), false) 682 pe.elemEnc(e, v.Elem(), false)
683 } 683 }
684 684
685 func buildPtrEncoder(t reflect.Type, vx reflect.Value) encoderFunc { 685 func newPtrEncoder(t reflect.Type, vx reflect.Value) encoderFunc {
686 enc := &ptrEncoder{typeEncoder(t.Elem(), reflect.Value{})} 686 enc := &ptrEncoder{typeEncoder(t.Elem(), reflect.Value{})}
687 return enc.encode 687 return enc.encode
688 } 688 }
689 689
690 func isValidTag(s string) bool { 690 func isValidTag(s string) bool {
691 if s == "" { 691 if s == "" {
692 return false 692 return false
693 } 693 }
694 for _, c := range s { 694 for _, c := range s {
695 switch { 695 switch {
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 } 1026 }
1027 1027
1028 fieldCache.Lock() 1028 fieldCache.Lock()
1029 if fieldCache.m == nil { 1029 if fieldCache.m == nil {
1030 fieldCache.m = map[reflect.Type][]field{} 1030 fieldCache.m = map[reflect.Type][]field{}
1031 } 1031 }
1032 fieldCache.m[t] = f 1032 fieldCache.m[t] = f
1033 fieldCache.Unlock() 1033 fieldCache.Unlock()
1034 return f 1034 return f
1035 } 1035 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b