github.com/instana/go-sensor@v1.62.2-0.20240520081010-4919868049e1/autoprofile/internal/pprof/profile/encode.go (about)

     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  }
   201  
   202  // postDecode takes the unexported fields populated by decode (with
   203  // suffix X) and populates the corresponding exported fields.
   204  // The unexported fields are cleared up to facilitate testing.
   205  func (p *Profile) postDecode() error {
   206  	var err error
   207  
   208  	mappings := make(map[uint64]*Mapping)
   209  	for _, m := range p.Mapping {
   210  		m.File, err = getString(p.stringTable, &m.fileX, err)
   211  		m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
   212  		mappings[m.ID] = m
   213  	}
   214  
   215  	functions := make(map[uint64]*Function)
   216  	for _, f := range p.Function {
   217  		f.Name, err = getString(p.stringTable, &f.nameX, err)
   218  		f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
   219  		f.Filename, err = getString(p.stringTable, &f.filenameX, err)
   220  		functions[f.ID] = f
   221  	}
   222  
   223  	locations := make(map[uint64]*Location)
   224  	for _, l := range p.Location {
   225  		l.Mapping = mappings[l.mappingIDX]
   226  		l.mappingIDX = 0
   227  		for i, ln := range l.Line {
   228  			if id := ln.functionIDX; id != 0 {
   229  				l.Line[i].Function = functions[id]
   230  				if l.Line[i].Function == nil {
   231  					return fmt.Errorf("Function ID %d not found", id)
   232  				}
   233  				l.Line[i].functionIDX = 0
   234  			}
   235  		}
   236  		locations[l.ID] = l
   237  	}
   238  
   239  	for _, st := range p.SampleType {
   240  		st.Type, err = getString(p.stringTable, &st.typeX, err)
   241  		st.Unit, err = getString(p.stringTable, &st.unitX, err)
   242  	}
   243  
   244  	for _, s := range p.Sample {
   245  		labels := make(map[string][]string)
   246  		numLabels := make(map[string][]int64)
   247  		for _, l := range s.labelX {
   248  			var key, value string
   249  			key, err = getString(p.stringTable, &l.keyX, err)
   250  			if l.strX != 0 {
   251  				value, err = getString(p.stringTable, &l.strX, err)
   252  				labels[key] = append(labels[key], value)
   253  			} else {
   254  				numLabels[key] = append(numLabels[key], l.numX)
   255  			}
   256  		}
   257  		if len(labels) > 0 {
   258  			s.Label = labels
   259  		}
   260  		if len(numLabels) > 0 {
   261  			s.NumLabel = numLabels
   262  		}
   263  		s.Location = nil
   264  		for _, lid := range s.locationIDX {
   265  			s.Location = append(s.Location, locations[lid])
   266  		}
   267  		s.locationIDX = nil
   268  	}
   269  
   270  	p.DropFrames, err = getString(p.stringTable, &p.dropFramesX, err)
   271  	p.KeepFrames, err = getString(p.stringTable, &p.keepFramesX, err)
   272  
   273  	if pt := p.PeriodType; pt == nil {
   274  		p.PeriodType = &ValueType{}
   275  	}
   276  
   277  	if pt := p.PeriodType; pt != nil {
   278  		pt.Type, err = getString(p.stringTable, &pt.typeX, err)
   279  		pt.Unit, err = getString(p.stringTable, &pt.unitX, err)
   280  	}
   281  
   282  	p.stringTable = nil
   283  	_ = err
   284  
   285  	return nil
   286  }
   287  
   288  func (p *ValueType) decoder() []decoder {
   289  	return valueTypeDecoder
   290  }
   291  
   292  func (p *ValueType) encode(b *buffer) {
   293  	encodeInt64Opt(b, 1, p.typeX)
   294  	encodeInt64Opt(b, 2, p.unitX)
   295  }
   296  
   297  var valueTypeDecoder = []decoder{
   298  	nil, // 0
   299  	// optional int64 type = 1
   300  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).typeX) },
   301  	// optional int64 unit = 2
   302  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).unitX) },
   303  }
   304  
   305  func (p *Sample) decoder() []decoder {
   306  	return sampleDecoder
   307  }
   308  
   309  func (p *Sample) encode(b *buffer) {
   310  	encodeUint64s(b, 1, p.locationIDX)
   311  	for _, x := range p.Value {
   312  		encodeInt64(b, 2, x)
   313  	}
   314  	for _, x := range p.labelX {
   315  		encodeMessage(b, 3, x)
   316  	}
   317  }
   318  
   319  var sampleDecoder = []decoder{
   320  	nil, // 0
   321  	// repeated uint64 location = 1
   322  	func(b *buffer, m message) error { return decodeUint64s(b, &m.(*Sample).locationIDX) },
   323  	// repeated int64 value = 2
   324  	func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Sample).Value) },
   325  	// repeated Label label = 3
   326  	func(b *buffer, m message) error {
   327  		s := m.(*Sample)
   328  		n := len(s.labelX)
   329  		s.labelX = append(s.labelX, Label{})
   330  		return decodeMessage(b, &s.labelX[n])
   331  	},
   332  }
   333  
   334  func (p Label) decoder() []decoder {
   335  	return labelDecoder
   336  }
   337  
   338  func (p Label) encode(b *buffer) {
   339  	encodeInt64Opt(b, 1, p.keyX)
   340  	encodeInt64Opt(b, 2, p.strX)
   341  	encodeInt64Opt(b, 3, p.numX)
   342  }
   343  
   344  var labelDecoder = []decoder{
   345  	nil, // 0
   346  	// optional int64 key = 1
   347  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).keyX) },
   348  	// optional int64 str = 2
   349  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).strX) },
   350  	// optional int64 num = 3
   351  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).numX) },
   352  }
   353  
   354  func (p *Mapping) decoder() []decoder {
   355  	return mappingDecoder
   356  }
   357  
   358  func (p *Mapping) encode(b *buffer) {
   359  	encodeUint64Opt(b, 1, p.ID)
   360  	encodeUint64Opt(b, 2, p.Start)
   361  	encodeUint64Opt(b, 3, p.Limit)
   362  	encodeUint64Opt(b, 4, p.Offset)
   363  	encodeInt64Opt(b, 5, p.fileX)
   364  	encodeInt64Opt(b, 6, p.buildIDX)
   365  	encodeBoolOpt(b, 7, p.HasFunctions)
   366  	encodeBoolOpt(b, 8, p.HasFilenames)
   367  	encodeBoolOpt(b, 9, p.HasLineNumbers)
   368  	encodeBoolOpt(b, 10, p.HasInlineFrames)
   369  }
   370  
   371  var mappingDecoder = []decoder{
   372  	nil, // 0
   373  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).ID) },            // optional uint64 id = 1
   374  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Start) },         // optional uint64 memory_offset = 2
   375  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Limit) },         // optional uint64 memory_limit = 3
   376  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Offset) },        // optional uint64 file_offset = 4
   377  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).fileX) },          // optional int64 filename = 5
   378  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).buildIDX) },       // optional int64 build_id = 6
   379  	func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFunctions) },    // optional bool has_functions = 7
   380  	func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFilenames) },    // optional bool has_filenames = 8
   381  	func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasLineNumbers) },  // optional bool has_line_numbers = 9
   382  	func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasInlineFrames) }, // optional bool has_inline_frames = 10
   383  }
   384  
   385  func (loc *Location) decoder() []decoder {
   386  	return locationDecoder
   387  }
   388  
   389  func (loc *Location) encode(b *buffer) {
   390  	encodeUint64Opt(b, 1, loc.ID)
   391  	encodeUint64Opt(b, 2, loc.mappingIDX)
   392  	encodeUint64Opt(b, 3, loc.Address)
   393  	for i := range loc.Line {
   394  		encodeMessage(b, 4, &loc.Line[i])
   395  	}
   396  }
   397  
   398  var locationDecoder = []decoder{
   399  	nil, // 0
   400  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).ID) },         // optional uint64 id = 1;
   401  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).mappingIDX) }, // optional uint64 mapping_id = 2;
   402  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).Address) },    // optional uint64 address = 3;
   403  	func(b *buffer, m message) error { // repeated Line line = 4
   404  		pp := m.(*Location)
   405  		n := len(pp.Line)
   406  		pp.Line = append(pp.Line, Line{})
   407  		return decodeMessage(b, &pp.Line[n])
   408  	},
   409  }
   410  
   411  func (p *Line) decoder() []decoder {
   412  	return lineDecoder
   413  }
   414  
   415  func (p *Line) encode(b *buffer) {
   416  	encodeUint64Opt(b, 1, p.functionIDX)
   417  	encodeInt64Opt(b, 2, p.Line)
   418  }
   419  
   420  var lineDecoder = []decoder{
   421  	nil, // 0
   422  	// optional uint64 function_id = 1
   423  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) },
   424  	// optional int64 line = 2
   425  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) },
   426  }
   427  
   428  func (p *Function) decoder() []decoder {
   429  	return functionDecoder
   430  }
   431  
   432  func (p *Function) encode(b *buffer) {
   433  	encodeUint64Opt(b, 1, p.ID)
   434  	encodeInt64Opt(b, 2, p.nameX)
   435  	encodeInt64Opt(b, 3, p.systemNameX)
   436  	encodeInt64Opt(b, 4, p.filenameX)
   437  	encodeInt64Opt(b, 5, p.StartLine)
   438  }
   439  
   440  var functionDecoder = []decoder{
   441  	nil, // 0
   442  	// optional uint64 id = 1
   443  	func(b *buffer, m message) error { return decodeUint64(b, &m.(*Function).ID) },
   444  	// optional int64 function_name = 2
   445  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).nameX) },
   446  	// optional int64 function_system_name = 3
   447  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).systemNameX) },
   448  	// repeated int64 filename = 4
   449  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).filenameX) },
   450  	// optional int64 start_line = 5
   451  	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).StartLine) },
   452  }
   453  
   454  func addString(strings map[string]int, s string) int64 {
   455  	i, ok := strings[s]
   456  	if !ok {
   457  		i = len(strings)
   458  		strings[s] = i
   459  	}
   460  	return int64(i)
   461  }
   462  
   463  func getString(strings []string, strng *int64, err error) (string, error) {
   464  	if err != nil {
   465  		return "", err
   466  	}
   467  	s := int(*strng)
   468  	if s < 0 || s >= len(strings) {
   469  		return "", errMalformed
   470  	}
   471  	*strng = 0
   472  	return strings[s], nil
   473  }