...

Source file src/runtime/pprof/internal/profile/encode.go

     1	// Copyright 2014 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	package profile
     6	
     7	import (
     8		"errors"
     9		"fmt"
    10		"sort"
    11	)
    12	
    13	func (p *Profile) decoder() []decoder {
    14		return profileDecoder
    15	}
    16	
    17	// preEncode populates the unexported fields to be used by encode
    18	// (with suffix X) from the corresponding exported fields. The
    19	// exported fields are cleared up to facilitate testing.
    20	func (p *Profile) preEncode() {
    21		strings := make(map[string]int)
    22		addString(strings, "")
    23	
    24		for _, st := range p.SampleType {
    25			st.typeX = addString(strings, st.Type)
    26			st.unitX = addString(strings, st.Unit)
    27		}
    28	
    29		for _, s := range p.Sample {
    30			s.labelX = nil
    31			var keys []string
    32			for k := range s.Label {
    33				keys = append(keys, k)
    34			}
    35			sort.Strings(keys)
    36			for _, k := range keys {
    37				vs := s.Label[k]
    38				for _, v := range vs {
    39					s.labelX = append(s.labelX,
    40						Label{
    41							keyX: addString(strings, k),
    42							strX: addString(strings, v),
    43						},
    44					)
    45				}
    46			}
    47			var numKeys []string
    48			for k := range s.NumLabel {
    49				numKeys = append(numKeys, k)
    50			}
    51			sort.Strings(numKeys)
    52			for _, k := range numKeys {
    53				vs := s.NumLabel[k]
    54				for _, v := range vs {
    55					s.labelX = append(s.labelX,
    56						Label{
    57							keyX: addString(strings, k),
    58							numX: v,
    59						},
    60					)
    61				}
    62			}
    63			s.locationIDX = nil
    64			for _, l := range s.Location {
    65				s.locationIDX = append(s.locationIDX, l.ID)
    66			}
    67		}
    68	
    69		for _, m := range p.Mapping {
    70			m.fileX = addString(strings, m.File)
    71			m.buildIDX = addString(strings, m.BuildID)
    72		}
    73	
    74		for _, l := range p.Location {
    75			for i, ln := range l.Line {
    76				if ln.Function != nil {
    77					l.Line[i].functionIDX = ln.Function.ID
    78				} else {
    79					l.Line[i].functionIDX = 0
    80				}
    81			}
    82			if l.Mapping != nil {
    83				l.mappingIDX = l.Mapping.ID
    84			} else {
    85				l.mappingIDX = 0
    86			}
    87		}
    88		for _, f := range p.Function {
    89			f.nameX = addString(strings, f.Name)
    90			f.systemNameX = addString(strings, f.SystemName)
    91			f.filenameX = addString(strings, f.Filename)
    92		}
    93	
    94		p.dropFramesX = addString(strings, p.DropFrames)
    95		p.keepFramesX = addString(strings, p.KeepFrames)
    96	
    97		if pt := p.PeriodType; pt != nil {
    98			pt.typeX = addString(strings, pt.Type)
    99			pt.unitX = addString(strings, pt.Unit)
   100		}
   101	
   102		p.stringTable = make([]string, len(strings))
   103		for s, i := range strings {
   104			p.stringTable[i] = s
   105		}
   106	}
   107	
   108	func (p *Profile) encode(b *buffer) {
   109		for _, x := range p.SampleType {
   110			encodeMessage(b, 1, x)
   111		}
   112		for _, x := range p.Sample {
   113			encodeMessage(b, 2, x)
   114		}
   115		for _, x := range p.Mapping {
   116			encodeMessage(b, 3, x)
   117		}
   118		for _, x := range p.Location {
   119			encodeMessage(b, 4, x)
   120		}
   121		for _, x := range p.Function {
   122			encodeMessage(b, 5, x)
   123		}
   124		encodeStrings(b, 6, p.stringTable)
   125		encodeInt64Opt(b, 7, p.dropFramesX)
   126		encodeInt64Opt(b, 8, p.keepFramesX)
   127		encodeInt64Opt(b, 9, p.TimeNanos)
   128		encodeInt64Opt(b, 10, p.DurationNanos)
   129		if pt := p.PeriodType; pt != nil && (pt.typeX != 0 || pt.unitX != 0) {
   130			encodeMessage(b, 11, p.PeriodType)
   131		}
   132		encodeInt64Opt(b, 12, p.Period)
   133	}
   134	
   135	var profileDecoder = []decoder{
   136		nil, // 0
   137		// repeated ValueType sample_type = 1
   138		func(b *buffer, m message) error {
   139			x := new(ValueType)
   140			pp := m.(*Profile)
   141			pp.SampleType = append(pp.SampleType, x)
   142			return decodeMessage(b, x)
   143		},
   144		// repeated Sample sample = 2
   145		func(b *buffer, m message) error {
   146			x := new(Sample)
   147			pp := m.(*Profile)
   148			pp.Sample = append(pp.Sample, x)
   149			return decodeMessage(b, x)
   150		},
   151		// repeated Mapping mapping = 3
   152		func(b *buffer, m message) error {
   153			x := new(Mapping)
   154			pp := m.(*Profile)
   155			pp.Mapping = append(pp.Mapping, x)
   156			return decodeMessage(b, x)
   157		},
   158		// repeated Location location = 4
   159		func(b *buffer, m message) error {
   160			x := new(Location)
   161			pp := m.(*Profile)
   162			pp.Location = append(pp.Location, x)
   163			return decodeMessage(b, x)
   164		},
   165		// repeated Function function = 5
   166		func(b *buffer, m message) error {
   167			x := new(Function)
   168			pp := m.(*Profile)
   169			pp.Function = append(pp.Function, x)
   170			return decodeMessage(b, x)
   171		},
   172		// repeated string string_table = 6
   173		func(b *buffer, m message) error {
   174			err := decodeStrings(b, &m.(*Profile).stringTable)
   175			if err != nil {
   176				return err
   177			}
   178			if *&m.(*Profile).stringTable[0] != "" {
   179				return errors.New("string_table[0] must be ''")
   180			}
   181			return nil
   182		},
   183		// repeated int64 drop_frames = 7
   184		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).dropFramesX) },
   185		// repeated int64 keep_frames = 8
   186		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).keepFramesX) },
   187		// repeated int64 time_nanos = 9
   188		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).TimeNanos) },
   189		// repeated int64 duration_nanos = 10
   190		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).DurationNanos) },
   191		// optional string period_type = 11
   192		func(b *buffer, m message) error {
   193			x := new(ValueType)
   194			pp := m.(*Profile)
   195			pp.PeriodType = x
   196			return decodeMessage(b, x)
   197		},
   198		// repeated int64 period = 12
   199		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).Period) },
   200		// repeated int64 comment = 13
   201		func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Profile).commentX) },
   202		// int64 defaultSampleType = 14
   203		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).defaultSampleTypeX) },
   204	}
   205	
   206	// postDecode takes the unexported fields populated by decode (with
   207	// suffix X) and populates the corresponding exported fields.
   208	// The unexported fields are cleared up to facilitate testing.
   209	func (p *Profile) postDecode() error {
   210		var err error
   211	
   212		mappings := make(map[uint64]*Mapping)
   213		for _, m := range p.Mapping {
   214			m.File, err = getString(p.stringTable, &m.fileX, err)
   215			m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
   216			mappings[m.ID] = m
   217		}
   218	
   219		functions := make(map[uint64]*Function)
   220		for _, f := range p.Function {
   221			f.Name, err = getString(p.stringTable, &f.nameX, err)
   222			f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
   223			f.Filename, err = getString(p.stringTable, &f.filenameX, err)
   224			functions[f.ID] = f
   225		}
   226	
   227		locations := make(map[uint64]*Location)
   228		for _, l := range p.Location {
   229			l.Mapping = mappings[l.mappingIDX]
   230			l.mappingIDX = 0
   231			for i, ln := range l.Line {
   232				if id := ln.functionIDX; id != 0 {
   233					l.Line[i].Function = functions[id]
   234					if l.Line[i].Function == nil {
   235						return fmt.Errorf("Function ID %d not found", id)
   236					}
   237					l.Line[i].functionIDX = 0
   238				}
   239			}
   240			locations[l.ID] = l
   241		}
   242	
   243		for _, st := range p.SampleType {
   244			st.Type, err = getString(p.stringTable, &st.typeX, err)
   245			st.Unit, err = getString(p.stringTable, &st.unitX, err)
   246		}
   247	
   248		for _, s := range p.Sample {
   249			labels := make(map[string][]string)
   250			numLabels := make(map[string][]int64)
   251			for _, l := range s.labelX {
   252				var key, value string
   253				key, err = getString(p.stringTable, &l.keyX, err)
   254				if l.strX != 0 {
   255					value, err = getString(p.stringTable, &l.strX, err)
   256					labels[key] = append(labels[key], value)
   257				} else {
   258					numLabels[key] = append(numLabels[key], l.numX)
   259				}
   260			}
   261			if len(labels) > 0 {
   262				s.Label = labels
   263			}
   264			if len(numLabels) > 0 {
   265				s.NumLabel = numLabels
   266			}
   267			s.Location = nil
   268			for _, lid := range s.locationIDX {
   269				s.Location = append(s.Location, locations[lid])
   270			}
   271			s.locationIDX = nil
   272		}
   273	
   274		p.DropFrames, err = getString(p.stringTable, &p.dropFramesX, err)
   275		p.KeepFrames, err = getString(p.stringTable, &p.keepFramesX, err)
   276	
   277		if pt := p.PeriodType; pt == nil {
   278			p.PeriodType = &ValueType{}
   279		}
   280	
   281		if pt := p.PeriodType; pt != nil {
   282			pt.Type, err = getString(p.stringTable, &pt.typeX, err)
   283			pt.Unit, err = getString(p.stringTable, &pt.unitX, err)
   284		}
   285		for _, i := range p.commentX {
   286			var c string
   287			c, err = getString(p.stringTable, &i, err)
   288			p.Comments = append(p.Comments, c)
   289		}
   290	
   291		p.commentX = nil
   292		p.DefaultSampleType, err = getString(p.stringTable, &p.defaultSampleTypeX, err)
   293		p.stringTable = nil
   294		return nil
   295	}
   296	
   297	func (p *ValueType) decoder() []decoder {
   298		return valueTypeDecoder
   299	}
   300	
   301	func (p *ValueType) encode(b *buffer) {
   302		encodeInt64Opt(b, 1, p.typeX)
   303		encodeInt64Opt(b, 2, p.unitX)
   304	}
   305	
   306	var valueTypeDecoder = []decoder{
   307		nil, // 0
   308		// optional int64 type = 1
   309		func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).typeX) },
   310		// optional int64 unit = 2
   311		func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).unitX) },
   312	}
   313	
   314	func (p *Sample) decoder() []decoder {
   315		return sampleDecoder
   316	}
   317	
   318	func (p *Sample) encode(b *buffer) {
   319		encodeUint64s(b, 1, p.locationIDX)
   320		for _, x := range p.Value {
   321			encodeInt64(b, 2, x)
   322		}
   323		for _, x := range p.labelX {
   324			encodeMessage(b, 3, x)
   325		}
   326	}
   327	
   328	var sampleDecoder = []decoder{
   329		nil, // 0
   330		// repeated uint64 location = 1
   331		func(b *buffer, m message) error { return decodeUint64s(b, &m.(*Sample).locationIDX) },
   332		// repeated int64 value = 2
   333		func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Sample).Value) },
   334		// repeated Label label = 3
   335		func(b *buffer, m message) error {
   336			s := m.(*Sample)
   337			n := len(s.labelX)
   338			s.labelX = append(s.labelX, Label{})
   339			return decodeMessage(b, &s.labelX[n])
   340		},
   341	}
   342	
   343	func (p Label) decoder() []decoder {
   344		return labelDecoder
   345	}
   346	
   347	func (p Label) encode(b *buffer) {
   348		encodeInt64Opt(b, 1, p.keyX)
   349		encodeInt64Opt(b, 2, p.strX)
   350		encodeInt64Opt(b, 3, p.numX)
   351	}
   352	
   353	var labelDecoder = []decoder{
   354		nil, // 0
   355		// optional int64 key = 1
   356		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).keyX) },
   357		// optional int64 str = 2
   358		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).strX) },
   359		// optional int64 num = 3
   360		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).numX) },
   361	}
   362	
   363	func (p *Mapping) decoder() []decoder {
   364		return mappingDecoder
   365	}
   366	
   367	func (p *Mapping) encode(b *buffer) {
   368		encodeUint64Opt(b, 1, p.ID)
   369		encodeUint64Opt(b, 2, p.Start)
   370		encodeUint64Opt(b, 3, p.Limit)
   371		encodeUint64Opt(b, 4, p.Offset)
   372		encodeInt64Opt(b, 5, p.fileX)
   373		encodeInt64Opt(b, 6, p.buildIDX)
   374		encodeBoolOpt(b, 7, p.HasFunctions)
   375		encodeBoolOpt(b, 8, p.HasFilenames)
   376		encodeBoolOpt(b, 9, p.HasLineNumbers)
   377		encodeBoolOpt(b, 10, p.HasInlineFrames)
   378	}
   379	
   380	var mappingDecoder = []decoder{
   381		nil, // 0
   382		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).ID) },            // optional uint64 id = 1
   383		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Start) },         // optional uint64 memory_offset = 2
   384		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Limit) },         // optional uint64 memory_limit = 3
   385		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Offset) },        // optional uint64 file_offset = 4
   386		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).fileX) },          // optional int64 filename = 5
   387		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).buildIDX) },       // optional int64 build_id = 6
   388		func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFunctions) },    // optional bool has_functions = 7
   389		func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFilenames) },    // optional bool has_filenames = 8
   390		func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasLineNumbers) },  // optional bool has_line_numbers = 9
   391		func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasInlineFrames) }, // optional bool has_inline_frames = 10
   392	}
   393	
   394	func (p *Location) decoder() []decoder {
   395		return locationDecoder
   396	}
   397	
   398	func (p *Location) encode(b *buffer) {
   399		encodeUint64Opt(b, 1, p.ID)
   400		encodeUint64Opt(b, 2, p.mappingIDX)
   401		encodeUint64Opt(b, 3, p.Address)
   402		for i := range p.Line {
   403			encodeMessage(b, 4, &p.Line[i])
   404		}
   405	}
   406	
   407	var locationDecoder = []decoder{
   408		nil, // 0
   409		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).ID) },         // optional uint64 id = 1;
   410		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).mappingIDX) }, // optional uint64 mapping_id = 2;
   411		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).Address) },    // optional uint64 address = 3;
   412		func(b *buffer, m message) error { // repeated Line line = 4
   413			pp := m.(*Location)
   414			n := len(pp.Line)
   415			pp.Line = append(pp.Line, Line{})
   416			return decodeMessage(b, &pp.Line[n])
   417		},
   418	}
   419	
   420	func (p *Line) decoder() []decoder {
   421		return lineDecoder
   422	}
   423	
   424	func (p *Line) encode(b *buffer) {
   425		encodeUint64Opt(b, 1, p.functionIDX)
   426		encodeInt64Opt(b, 2, p.Line)
   427	}
   428	
   429	var lineDecoder = []decoder{
   430		nil, // 0
   431		// optional uint64 function_id = 1
   432		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) },
   433		// optional int64 line = 2
   434		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) },
   435	}
   436	
   437	func (p *Function) decoder() []decoder {
   438		return functionDecoder
   439	}
   440	
   441	func (p *Function) encode(b *buffer) {
   442		encodeUint64Opt(b, 1, p.ID)
   443		encodeInt64Opt(b, 2, p.nameX)
   444		encodeInt64Opt(b, 3, p.systemNameX)
   445		encodeInt64Opt(b, 4, p.filenameX)
   446		encodeInt64Opt(b, 5, p.StartLine)
   447	}
   448	
   449	var functionDecoder = []decoder{
   450		nil, // 0
   451		// optional uint64 id = 1
   452		func(b *buffer, m message) error { return decodeUint64(b, &m.(*Function).ID) },
   453		// optional int64 function_name = 2
   454		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).nameX) },
   455		// optional int64 function_system_name = 3
   456		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).systemNameX) },
   457		// repeated int64 filename = 4
   458		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).filenameX) },
   459		// optional int64 start_line = 5
   460		func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).StartLine) },
   461	}
   462	
   463	func addString(strings map[string]int, s string) int64 {
   464		i, ok := strings[s]
   465		if !ok {
   466			i = len(strings)
   467			strings[s] = i
   468		}
   469		return int64(i)
   470	}
   471	
   472	func getString(strings []string, strng *int64, err error) (string, error) {
   473		if err != nil {
   474			return "", err
   475		}
   476		s := int(*strng)
   477		if s < 0 || s >= len(strings) {
   478			return "", errMalformed
   479		}
   480		*strng = 0
   481		return strings[s], nil
   482	}
   483	

View as plain text