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 }