Browse Source

Misc changes suggested by readability review

Should have no functional changes
Raul Silvera 8 years ago
parent
commit
9714e5d100
4 changed files with 109 additions and 166 deletions
  1. 1
    1
      profile/encode.go
  2. 101
    159
      profile/legacy_profile.go
  3. 1
    1
      profile/profile.go
  4. 6
    5
      profile/proto.go

+ 1
- 1
profile/encode.go View File

197
 		if err != nil {
197
 		if err != nil {
198
 			return err
198
 			return err
199
 		}
199
 		}
200
-		if *&m.(*Profile).stringTable[0] != "" {
200
+		if m.(*Profile).stringTable[0] != "" {
201
 			return errors.New("string_table[0] must be ''")
201
 			return errors.New("string_table[0] must be ''")
202
 		}
202
 		}
203
 		return nil
203
 		return nil

+ 101
- 159
profile/legacy_profile.go View File

29
 )
29
 )
30
 
30
 
31
 var (
31
 var (
32
-	countStartRE = regexp.MustCompile(`\A(\w+) profile: total \d+\n\z`)
33
-	countRE      = regexp.MustCompile(`\A(\d+) @(( 0x[0-9a-f]+)+)\n\z`)
32
+	countStartRE = regexp.MustCompile(`\A(\w+) profile: total \d+\z`)
33
+	countRE      = regexp.MustCompile(`\A(\d+) @(( 0x[0-9a-f]+)+)\z`)
34
 
34
 
35
 	heapHeaderRE = regexp.MustCompile(`heap profile: *(\d+): *(\d+) *\[ *(\d+): *(\d+) *\] *@ *(heap[_a-z0-9]*)/?(\d*)`)
35
 	heapHeaderRE = regexp.MustCompile(`heap profile: *(\d+): *(\d+) *\[ *(\d+): *(\d+) *\] *@ *(heap[_a-z0-9]*)/?(\d*)`)
36
 	heapSampleRE = regexp.MustCompile(`(-?\d+): *(-?\d+) *\[ *(\d+): *(\d+) *] @([ x0-9a-f]*)`)
36
 	heapSampleRE = regexp.MustCompile(`(-?\d+): *(-?\d+) *\[ *(\d+): *(\d+) *] @([ x0-9a-f]*)`)
59
 // parseGoCount parses a Go count profile (e.g., threadcreate or
59
 // parseGoCount parses a Go count profile (e.g., threadcreate or
60
 // goroutine) and returns a new Profile.
60
 // goroutine) and returns a new Profile.
61
 func parseGoCount(b []byte) (*Profile, error) {
61
 func parseGoCount(b []byte) (*Profile, error) {
62
-	r := bytes.NewBuffer(b)
63
-
64
-	var line string
65
-	var err error
66
-	for {
67
-		// Skip past comments and empty lines seeking a real header.
68
-		line, err = r.ReadString('\n')
69
-		if err != nil {
70
-			return nil, err
71
-		}
72
-		if !isSpaceOrComment(line) {
73
-			break
74
-		}
62
+	s := bufio.NewScanner(bytes.NewBuffer(b))
63
+	// Skip comments at the beginning of the file.
64
+	for s.Scan() && isSpaceOrComment(s.Text()) {
75
 	}
65
 	}
76
-
77
-	m := countStartRE.FindStringSubmatch(line)
66
+	if err := s.Err(); err != nil {
67
+		return nil, err
68
+	}
69
+	m := countStartRE.FindStringSubmatch(s.Text())
78
 	if m == nil {
70
 	if m == nil {
79
 		return nil, errUnrecognized
71
 		return nil, errUnrecognized
80
 	}
72
 	}
85
 		SampleType: []*ValueType{{Type: profileType, Unit: "count"}},
77
 		SampleType: []*ValueType{{Type: profileType, Unit: "count"}},
86
 	}
78
 	}
87
 	locations := make(map[uint64]*Location)
79
 	locations := make(map[uint64]*Location)
88
-	for {
89
-		line, err = r.ReadString('\n')
90
-		if err != nil {
91
-			if err == io.EOF {
92
-				break
93
-			}
94
-			return nil, err
95
-		}
80
+	for s.Scan() {
81
+		line := s.Text()
96
 		if isSpaceOrComment(line) {
82
 		if isSpaceOrComment(line) {
97
 			continue
83
 			continue
98
 		}
84
 		}
131
 			Value:    []int64{n},
117
 			Value:    []int64{n},
132
 		})
118
 		})
133
 	}
119
 	}
120
+	if err := s.Err(); err != nil {
121
+		return nil, err
122
+	}
134
 
123
 
135
-	if err = parseAdditionalSections(strings.TrimSpace(line), r, p); err != nil {
124
+	if err := parseAdditionalSections(s, p); err != nil {
136
 		return nil, err
125
 		return nil, err
137
 	}
126
 	}
138
 	return p, nil
127
 	return p, nil
455
 // parseHeap parses a heapz legacy or a growthz profile and
444
 // parseHeap parses a heapz legacy or a growthz profile and
456
 // returns a newly populated Profile.
445
 // returns a newly populated Profile.
457
 func parseHeap(b []byte) (p *Profile, err error) {
446
 func parseHeap(b []byte) (p *Profile, err error) {
458
-	r := bytes.NewBuffer(b)
459
-	l, err := r.ReadString('\n')
460
-	if err != nil {
461
-		return nil, errUnrecognized
447
+	s := bufio.NewScanner(bytes.NewBuffer(b))
448
+	if !s.Scan() {
449
+		return nil, s.Err()
462
 	}
450
 	}
463
-
464
 	p = &Profile{}
451
 	p = &Profile{}
465
 
452
 
466
 	sampling := ""
453
 	sampling := ""
467
 	hasAlloc := false
454
 	hasAlloc := false
468
 
455
 
456
+	line := s.Text()
469
 	p.PeriodType = &ValueType{Type: "space", Unit: "bytes"}
457
 	p.PeriodType = &ValueType{Type: "space", Unit: "bytes"}
470
-	if header := heapHeaderRE.FindStringSubmatch(l); header != nil {
471
-		sampling, p.Period, hasAlloc, err = parseHeapHeader(l)
458
+	if header := heapHeaderRE.FindStringSubmatch(line); header != nil {
459
+		sampling, p.Period, hasAlloc, err = parseHeapHeader(line)
472
 		if err != nil {
460
 		if err != nil {
473
 			return nil, err
461
 			return nil, err
474
 		}
462
 		}
475
-	} else if header = growthHeaderRE.FindStringSubmatch(l); header != nil {
463
+	} else if header = growthHeaderRE.FindStringSubmatch(line); header != nil {
476
 		p.Period = 1
464
 		p.Period = 1
477
-	} else if header = fragmentationHeaderRE.FindStringSubmatch(l); header != nil {
465
+	} else if header = fragmentationHeaderRE.FindStringSubmatch(line); header != nil {
478
 		p.Period = 1
466
 		p.Period = 1
479
 	} else {
467
 	} else {
480
 		return nil, errUnrecognized
468
 		return nil, errUnrecognized
497
 	}
485
 	}
498
 
486
 
499
 	locs := make(map[uint64]*Location)
487
 	locs := make(map[uint64]*Location)
500
-	for {
501
-		l, err = r.ReadString('\n')
502
-		if err != nil {
503
-			if err != io.EOF {
504
-				return nil, err
505
-			}
488
+	for s.Scan() {
489
+		line := strings.TrimSpace(s.Text())
506
 
490
 
507
-			if l == "" {
508
-				break
509
-			}
510
-		}
511
-
512
-		if isSpaceOrComment(l) {
491
+		if isSpaceOrComment(line) {
513
 			continue
492
 			continue
514
 		}
493
 		}
515
-		l = strings.TrimSpace(l)
516
 
494
 
517
-		if sectionTrigger(l) != unrecognizedSection {
495
+		if sectionTrigger(line) != unrecognizedSection {
518
 			break
496
 			break
519
 		}
497
 		}
520
 
498
 
521
-		value, blocksize, addrs, err := parseHeapSample(l, p.Period, sampling, hasAlloc)
499
+		value, blocksize, addrs, err := parseHeapSample(line, p.Period, sampling, hasAlloc)
522
 		if err != nil {
500
 		if err != nil {
523
 			return nil, err
501
 			return nil, err
524
 		}
502
 		}
545
 			NumLabel: map[string][]int64{"bytes": {blocksize}},
523
 			NumLabel: map[string][]int64{"bytes": {blocksize}},
546
 		})
524
 		})
547
 	}
525
 	}
548
-
549
-	if err = parseAdditionalSections(l, r, p); err != nil {
526
+	if err := s.Err(); err != nil {
527
+		return nil, err
528
+	}
529
+	if err := parseAdditionalSections(s, p); err != nil {
550
 		return nil, err
530
 		return nil, err
551
 	}
531
 	}
552
 	return p, nil
532
 	return p, nil
678
 // parseContention parses a contentionz profile and returns a newly
658
 // parseContention parses a contentionz profile and returns a newly
679
 // populated Profile.
659
 // populated Profile.
680
 func parseContention(b []byte) (p *Profile, err error) {
660
 func parseContention(b []byte) (p *Profile, err error) {
681
-	r := bytes.NewBuffer(b)
682
-	l, err := r.ReadString('\n')
683
-	if err != nil {
684
-		return nil, errUnrecognized
661
+	s := bufio.NewScanner(bytes.NewBuffer(b))
662
+	if !s.Scan() {
663
+		return nil, s.Err()
685
 	}
664
 	}
665
+	line := s.Text()
686
 
666
 
687
-	if !strings.HasPrefix(l, "--- contention") {
667
+	if !strings.HasPrefix(line, "--- contention") {
688
 		return nil, errUnrecognized
668
 		return nil, errUnrecognized
689
 	}
669
 	}
690
 
670
 
700
 	var cpuHz int64
680
 	var cpuHz int64
701
 	// Parse text of the form "attribute = value" before the samples.
681
 	// Parse text of the form "attribute = value" before the samples.
702
 	const delimiter = "="
682
 	const delimiter = "="
703
-	for {
704
-		l, err = r.ReadString('\n')
705
-		if err != nil {
706
-			if err != io.EOF {
707
-				return nil, err
708
-			}
709
-
710
-			if l == "" {
711
-				break
712
-			}
713
-		}
683
+	for s.Scan() {
684
+		line := s.Text()
714
 
685
 
715
-		if l = strings.TrimSpace(l); l == "" {
686
+		if line = strings.TrimSpace(line); line == "" {
716
 			continue
687
 			continue
717
 		}
688
 		}
718
 
689
 
719
-		if strings.HasPrefix(l, "---") {
690
+		if strings.HasPrefix(line, "---") {
720
 			break
691
 			break
721
 		}
692
 		}
722
 
693
 
723
-		attr := strings.SplitN(l, delimiter, 2)
694
+		attr := strings.SplitN(line, delimiter, 2)
724
 		if len(attr) != 2 {
695
 		if len(attr) != 2 {
725
 			break
696
 			break
726
 		}
697
 		}
752
 			return nil, errUnrecognized
723
 			return nil, errUnrecognized
753
 		}
724
 		}
754
 	}
725
 	}
726
+	if err := s.Err(); err != nil {
727
+		return nil, err
728
+	}
755
 
729
 
756
 	locs := make(map[uint64]*Location)
730
 	locs := make(map[uint64]*Location)
757
 	for {
731
 	for {
758
-		if l = strings.TrimSpace(l); strings.HasPrefix(l, "---") {
732
+		line := strings.TrimSpace(s.Text())
733
+		if strings.HasPrefix(line, "---") {
759
 			break
734
 			break
760
 		}
735
 		}
761
-		value, addrs, err := parseContentionSample(l, p.Period, cpuHz)
736
+		value, addrs, err := parseContentionSample(line, p.Period, cpuHz)
762
 		if err != nil {
737
 		if err != nil {
763
 			return nil, err
738
 			return nil, err
764
 		}
739
 		}
782
 			Location: sloc,
757
 			Location: sloc,
783
 		})
758
 		})
784
 
759
 
785
-		if l, err = r.ReadString('\n'); err != nil {
786
-			if err != io.EOF {
787
-				return nil, err
788
-			}
789
-			if l == "" {
790
-				break
791
-			}
760
+		if !s.Scan() {
761
+			break
792
 		}
762
 		}
793
 	}
763
 	}
764
+	if err := s.Err(); err != nil {
765
+		return nil, err
766
+	}
794
 
767
 
795
-	if err = parseAdditionalSections(l, r, p); err != nil {
768
+	if err = parseAdditionalSections(s, p); err != nil {
796
 		return nil, err
769
 		return nil, err
797
 	}
770
 	}
798
 
771
 
835
 
808
 
836
 // parseThread parses a Threadz profile and returns a new Profile.
809
 // parseThread parses a Threadz profile and returns a new Profile.
837
 func parseThread(b []byte) (*Profile, error) {
810
 func parseThread(b []byte) (*Profile, error) {
838
-	r := bytes.NewBuffer(b)
839
-
840
-	var line string
841
-	var err error
842
-	for {
843
-		// Skip past comments and empty lines seeking a real header.
844
-		line, err = r.ReadString('\n')
845
-		if err != nil {
846
-			return nil, err
847
-		}
848
-		if !isSpaceOrComment(line) {
849
-			break
850
-		}
811
+	s := bufio.NewScanner(bytes.NewBuffer(b))
812
+	// Skip past comments and empty lines seeking a real header.
813
+	for s.Scan() && isSpaceOrComment(s.Text()) {
851
 	}
814
 	}
852
 
815
 
816
+	line := s.Text()
853
 	if m := threadzStartRE.FindStringSubmatch(line); m != nil {
817
 	if m := threadzStartRE.FindStringSubmatch(line); m != nil {
854
 		// Advance over initial comments until first stack trace.
818
 		// Advance over initial comments until first stack trace.
855
-		for {
856
-			line, err = r.ReadString('\n')
857
-			if err != nil {
858
-				if err != io.EOF {
859
-					return nil, err
860
-				}
861
-
862
-				if line == "" {
863
-					break
864
-				}
865
-			}
866
-			if sectionTrigger(line) != unrecognizedSection || line[0] == '-' {
819
+		for s.Scan() {
820
+			if line = s.Text(); sectionTrigger(line) != unrecognizedSection || strings.HasPrefix(line, "-") {
867
 				break
821
 				break
868
 			}
822
 			}
869
 		}
823
 		}
889
 		}
843
 		}
890
 
844
 
891
 		var addrs []uint64
845
 		var addrs []uint64
892
-		line, addrs, err = parseThreadSample(r)
846
+		var err error
847
+		line, addrs, err = parseThreadSample(s)
893
 		if err != nil {
848
 		if err != nil {
894
 			return nil, errUnrecognized
849
 			return nil, errUnrecognized
895
 		}
850
 		}
927
 		})
882
 		})
928
 	}
883
 	}
929
 
884
 
930
-	if err = parseAdditionalSections(line, r, p); err != nil {
885
+	if err := parseAdditionalSections(s, p); err != nil {
931
 		return nil, err
886
 		return nil, err
932
 	}
887
 	}
933
 
888
 
938
 // parseThreadSample parses a symbolized or unsymbolized stack trace.
893
 // parseThreadSample parses a symbolized or unsymbolized stack trace.
939
 // Returns the first line after the traceback, the sample (or nil if
894
 // Returns the first line after the traceback, the sample (or nil if
940
 // it hits a 'same-as-previous' marker) and an error.
895
 // it hits a 'same-as-previous' marker) and an error.
941
-func parseThreadSample(b *bytes.Buffer) (nextl string, addrs []uint64, err error) {
942
-	var l string
896
+func parseThreadSample(s *bufio.Scanner) (nextl string, addrs []uint64, err error) {
897
+	var line string
943
 	sameAsPrevious := false
898
 	sameAsPrevious := false
944
-	for {
945
-		if l, err = b.ReadString('\n'); err != nil {
946
-			if err != io.EOF {
947
-				return "", nil, err
948
-			}
949
-			if l == "" {
950
-				break
951
-			}
952
-		}
953
-		if l = strings.TrimSpace(l); l == "" {
899
+	for s.Scan() {
900
+		line = strings.TrimSpace(s.Text())
901
+		if line == "" {
954
 			continue
902
 			continue
955
 		}
903
 		}
956
 
904
 
957
-		if strings.HasPrefix(l, "---") {
905
+		if strings.HasPrefix(line, "---") {
958
 			break
906
 			break
959
 		}
907
 		}
960
-		if strings.Contains(l, "same as previous thread") {
908
+		if strings.Contains(line, "same as previous thread") {
961
 			sameAsPrevious = true
909
 			sameAsPrevious = true
962
 			continue
910
 			continue
963
 		}
911
 		}
964
 
912
 
965
-		addrs = append(addrs, parseHexAddresses(l)...)
913
+		addrs = append(addrs, parseHexAddresses(line)...)
914
+	}
915
+	if s.Err() != nil {
916
+		return "", nil, s.Err()
966
 	}
917
 	}
967
-
968
 	if sameAsPrevious {
918
 	if sameAsPrevious {
969
-		return l, nil, nil
919
+		return line, nil, nil
970
 	}
920
 	}
971
-	return l, addrs, nil
921
+	return line, addrs, nil
972
 }
922
 }
973
 
923
 
974
 // parseAdditionalSections parses any additional sections in the
924
 // parseAdditionalSections parses any additional sections in the
975
 // profile, ignoring any unrecognized sections.
925
 // profile, ignoring any unrecognized sections.
976
-func parseAdditionalSections(l string, b *bytes.Buffer, p *Profile) error {
977
-	for {
978
-		if sectionTrigger(l) == memoryMapSection {
979
-			break
980
-		}
981
-		// Ignore any unrecognized sections.
982
-		var err error
983
-		if l, err = b.ReadString('\n'); err != nil {
984
-			if err != io.EOF {
985
-				return err
986
-			}
987
-			if l == "" {
988
-				break
989
-			}
990
-		}
926
+func parseAdditionalSections(s *bufio.Scanner, p *Profile) error {
927
+	for sectionTrigger(s.Text()) != memoryMapSection && s.Scan() {
991
 	}
928
 	}
992
-	return p.ParseMemoryMap(b)
929
+	if err := s.Err(); err != nil {
930
+		return err
931
+	}
932
+	return p.parseMemoryMapFromScanner(s)
993
 }
933
 }
994
 
934
 
995
 // ParseProcMaps parses a memory map in the format of /proc/self/maps.
935
 // ParseProcMaps parses a memory map in the format of /proc/self/maps.
997
 // associate locations to the corresponding mapping based on their
937
 // associate locations to the corresponding mapping based on their
998
 // address.
938
 // address.
999
 func ParseProcMaps(rd io.Reader) ([]*Mapping, error) {
939
 func ParseProcMaps(rd io.Reader) ([]*Mapping, error) {
1000
-	var mapping []*Mapping
940
+	s := bufio.NewScanner(rd)
941
+	return parseProcMapsFromScanner(s)
942
+}
1001
 
943
 
1002
-	b := bufio.NewReader(rd)
944
+func parseProcMapsFromScanner(s *bufio.Scanner) ([]*Mapping, error) {
945
+	var mapping []*Mapping
1003
 
946
 
1004
 	var attrs []string
947
 	var attrs []string
1005
 	var r *strings.Replacer
948
 	var r *strings.Replacer
1006
 	const delimiter = "="
949
 	const delimiter = "="
1007
-	for {
1008
-		l, err := b.ReadString('\n')
1009
-		if err != nil {
1010
-			if err != io.EOF {
1011
-				return nil, err
1012
-			}
1013
-			if l == "" {
1014
-				break
1015
-			}
1016
-		}
1017
-		if l = strings.TrimSpace(l); l == "" {
950
+	for s.Scan() {
951
+		line := strings.TrimSpace(s.Text())
952
+		if line == "" {
1018
 			continue
953
 			continue
1019
 		}
954
 		}
1020
 
955
 
1021
 		if r != nil {
956
 		if r != nil {
1022
-			l = r.Replace(l)
957
+			line = r.Replace(line)
1023
 		}
958
 		}
1024
-		m, err := parseMappingEntry(l)
959
+		m, err := parseMappingEntry(line)
1025
 		if err != nil {
960
 		if err != nil {
1026
 			if err == errUnrecognized {
961
 			if err == errUnrecognized {
1027
 				// Recognize assignments of the form: attr=value, and replace
962
 				// Recognize assignments of the form: attr=value, and replace
1028
 				// $attr with value on subsequent mappings.
963
 				// $attr with value on subsequent mappings.
1029
-				if attr := strings.SplitN(l, delimiter, 2); len(attr) == 2 {
964
+				if attr := strings.SplitN(line, delimiter, 2); len(attr) == 2 {
1030
 					attrs = append(attrs, "$"+strings.TrimSpace(attr[0]), strings.TrimSpace(attr[1]))
965
 					attrs = append(attrs, "$"+strings.TrimSpace(attr[0]), strings.TrimSpace(attr[1]))
1031
 					r = strings.NewReplacer(attrs...)
966
 					r = strings.NewReplacer(attrs...)
1032
 				}
967
 				}
1040
 		}
975
 		}
1041
 		mapping = append(mapping, m)
976
 		mapping = append(mapping, m)
1042
 	}
977
 	}
978
+	if err := s.Err(); err != nil {
979
+		return nil, err
980
+	}
1043
 	return mapping, nil
981
 	return mapping, nil
1044
 }
982
 }
1045
 
983
 
1047
 // /proc/self/maps, and overrides the mappings in the current profile.
985
 // /proc/self/maps, and overrides the mappings in the current profile.
1048
 // It renumbers the samples and locations in the profile correspondingly.
986
 // It renumbers the samples and locations in the profile correspondingly.
1049
 func (p *Profile) ParseMemoryMap(rd io.Reader) error {
987
 func (p *Profile) ParseMemoryMap(rd io.Reader) error {
1050
-	mapping, err := ParseProcMaps(rd)
988
+	return p.parseMemoryMapFromScanner(bufio.NewScanner(rd))
989
+}
990
+
991
+func (p *Profile) parseMemoryMapFromScanner(s *bufio.Scanner) error {
992
+	mapping, err := parseProcMapsFromScanner(s)
1051
 	if err != nil {
993
 	if err != nil {
1052
 		return err
994
 		return err
1053
 	}
995
 	}

+ 1
- 1
profile/profile.go View File

240
 		if len(libRx.FindStringSubmatch(file)) > 0 {
240
 		if len(libRx.FindStringSubmatch(file)) > 0 {
241
 			continue
241
 			continue
242
 		}
242
 		}
243
-		if strings.HasPrefix(file, "[") {
243
+		if file[0] == '[' {
244
 			continue
244
 			continue
245
 		}
245
 		}
246
 		// Swap what we guess is main to position 0.
246
 		// Swap what we guess is main to position 0.

+ 6
- 5
profile/proto.go View File

13
 // limitations under the License.
13
 // limitations under the License.
14
 
14
 
15
 // This file is a simple protocol buffer encoder and decoder.
15
 // This file is a simple protocol buffer encoder and decoder.
16
+// The format is described at
17
+// https://developers.google.com/protocol-buffers/docs/encoding
16
 //
18
 //
17
 // A protocol message must implement the message interface:
19
 // A protocol message must implement the message interface:
18
 //   decoder() []decoder
20
 //   decoder() []decoder
34
 import "errors"
36
 import "errors"
35
 
37
 
36
 type buffer struct {
38
 type buffer struct {
37
-	field int
38
-	typ   int
39
+	field int // field tag
40
+	typ   int // proto wire type code for field
39
 	u64   uint64
41
 	u64   uint64
40
 	data  []byte
42
 	data  []byte
41
 	tmp   [16]byte
43
 	tmp   [16]byte
190
 }
192
 }
191
 
193
 
192
 func decodeVarint(data []byte) (uint64, []byte, error) {
194
 func decodeVarint(data []byte) (uint64, []byte, error) {
193
-	var i int
194
 	var u uint64
195
 	var u uint64
195
-	for i = 0; ; i++ {
196
+	for i := 0; ; i++ {
196
 		if i >= 10 || i >= len(data) {
197
 		if i >= 10 || i >= len(data) {
197
 			return 0, nil, errors.New("bad varint")
198
 			return 0, nil, errors.New("bad varint")
198
 		}
199
 		}
242
 		b.u64 = uint64(le32(data[:4]))
243
 		b.u64 = uint64(le32(data[:4]))
243
 		data = data[4:]
244
 		data = data[4:]
244
 	default:
245
 	default:
245
-		return nil, errors.New("unknown type: " + string(b.typ))
246
+		return nil, errors.New("unknown wire type: " + string(b.typ))
246
 	}
247
 	}
247
 
248
 
248
 	return data, nil
249
 	return data, nil