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