in pkg/helper/profile/pyroscope/jfr/parser.go [64:162]
func (r *RawProfile) parseChunk(ctx context.Context, meta *profile.Meta, c parser.Chunk, jfrLabels *LabelsSnapshot, convertCb profile.CallbackFunc) {
stackMap := make(map[uint64]*profile.Stack)
valMap := make(map[uint64][]uint64)
labelMap := make(map[uint64]map[string]string)
typeMap := make(map[uint64][]string)
unitMap := make(map[uint64][]string)
aggtypeMap := make(map[uint64][]string)
var event string
for _, e := range c.Events {
if as, ok := e.(*parser.ActiveSetting); ok {
if as.Name == "event" {
event = as.Value
}
}
}
cache := make(tree.LabelsCache)
for contextID, events := range groupEventsByContextID(c.Events) {
labels := getContextLabels(contextID, jfrLabels)
lh := labels.Hash()
for _, e := range events {
switch obj := e.(type) {
case *parser.ExecutionSample:
if fs := frames(obj.StackTrace); fs != nil {
if obj.State.Name == "STATE_RUNNABLE" {
cache.GetOrCreateTreeByHash(sampleTypeCPU, labels, lh).InsertStackString(fs, 1)
}
cache.GetOrCreateTreeByHash(sampleTypeWall, labels, lh).InsertStackString(fs, 1)
}
case *parser.ObjectAllocationInNewTLAB:
if fs := frames(obj.StackTrace); fs != nil {
cache.GetOrCreateTreeByHash(sampleTypeInTLABObjects, labels, lh).InsertStackString(fs, 1)
cache.GetOrCreateTreeByHash(sampleTypeInTLABBytes, labels, lh).InsertStackString(fs, uint64(obj.TLABSize))
}
case *parser.ObjectAllocationOutsideTLAB:
if fs := frames(obj.StackTrace); fs != nil {
cache.GetOrCreateTreeByHash(sampleTypeOutTLABObjects, labels, lh).InsertStackString(fs, 1)
cache.GetOrCreateTreeByHash(sampleTypeOutTLABBytes, labels, lh).InsertStackString(fs, uint64(obj.AllocationSize))
}
case *parser.JavaMonitorEnter:
if fs := frames(obj.StackTrace); fs != nil {
cache.GetOrCreateTreeByHash(sampleTypeLockSamples, labels, lh).InsertStackString(fs, 1)
cache.GetOrCreateTreeByHash(sampleTypeLockDuration, labels, lh).InsertStackString(fs, uint64(obj.Duration))
}
case *parser.ThreadPark:
if fs := frames(obj.StackTrace); fs != nil {
cache.GetOrCreateTreeByHash(sampleTypeLockSamples, labels, lh).InsertStackString(fs, 1)
cache.GetOrCreateTreeByHash(sampleTypeLockDuration, labels, lh).InsertStackString(fs, uint64(obj.Duration))
}
}
}
}
for sampleType, entries := range cache {
for _, e := range entries {
if i := labelIndex(jfrLabels, e.Labels, segment.ProfileIDLabelName); i != -1 {
cutLabels := tree.CutLabel(e.Labels, i)
cache.GetOrCreateTree(sampleType, cutLabels).Merge(e.Tree)
}
}
}
cb := func(n string, labels tree.Labels, t *tree.Tree, u profile.Units) {
t.IterateStacks(func(name string, self uint64, stack []string) {
unit := u
if u == profile.SamplesUnits {
unit = profile.NanosecondsUnit
self *= uint64(time.Second.Nanoseconds() / int64(meta.SampleRate))
}
id := xxhash.Sum64String(strings.Join(stack, ""))
stackMap[id] = &profile.Stack{
Name: profile.FormatPositionAndName(name, profile.FormatType(meta.SpyName)),
Stack: profile.FormatPostionAndNames(stack[1:], profile.FormatType(meta.SpyName)),
}
aggtypeMap[id] = append(aggtypeMap[id], string(meta.AggregationType))
typeMap[id] = append(typeMap[id], n)
unitMap[id] = append(unitMap[id], string(unit))
valMap[id] = append(valMap[id], self)
labelMap[id] = buildKey(meta.Tags, labels, jfrLabels).Labels()
})
}
for sampleType, entries := range cache {
if sampleType == sampleTypeWall && event != "wall" {
continue
}
n := getName(sampleType, event)
units := getUnits(sampleType)
for _, e := range entries {
cb(n, e.Labels, e.Tree, units)
}
}
for id, fs := range stackMap {
if len(valMap[id]) == 0 || len(typeMap[id]) == 0 || len(unitMap[id]) == 0 || len(aggtypeMap[id]) == 0 || len(labelMap[id]) == 0 {
logger.Warning(ctx, "PPROF_PROFILE_ALARM", "stack don't have enough meta or values", fs)
continue
}
convertCb(id, fs, valMap[id], typeMap[id], unitMap[id], aggtypeMap[id], meta.StartTime.UnixNano(), meta.EndTime.UnixNano(), labelMap[id])
}
}