summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-27 08:10:40 +0300
committerPaul Buetow <paul@buetow.org>2026-05-27 08:10:40 +0300
commit987ba21a5ff69b82bd56012866634cabf6670194 (patch)
tree7d4259ac5a18da44b32819736f16c902cd5ef760
parent9b6be4cf0fcaf6426886c2a0ecf55f06965f1a3f (diff)
flamegraph: reduce AddRecord lock contention (6p)
-rw-r--r--internal/flamegraph/livetrie.go52
1 files changed, 34 insertions, 18 deletions
diff --git a/internal/flamegraph/livetrie.go b/internal/flamegraph/livetrie.go
index 4554780..188ba6a 100644
--- a/internal/flamegraph/livetrie.go
+++ b/internal/flamegraph/livetrie.go
@@ -100,28 +100,44 @@ func (lt *LiveTrie) Ingest(ep *event.Pair) {
lt.AddRecord(record)
}
+func (lt *LiveTrie) addRecordConfig() ([]string, string, string) {
+ lt.mu.RLock()
+ fields := slices.Clone(lt.fields)
+ countField := lt.countField
+ heightField := lt.heightField
+ lt.mu.RUnlock()
+ return fields, countField, heightField
+}
+
// AddRecord adds one already-decoded flamegraph record into the live trie.
func (lt *LiveTrie) AddRecord(record IterRecord) {
- lt.mu.Lock()
+ for {
+ fields, countField, heightField := lt.addRecordConfig()
- value, err := record.Cnt.ValueByName(lt.countField)
- if err != nil {
- lt.mu.Unlock()
- return
- }
- heightValue := uint64(0)
- if lt.heightField != "" {
- heightValue, err = record.Cnt.ValueByName(lt.heightField)
+ value, err := record.Cnt.ValueByName(countField)
if err != nil {
- lt.mu.Unlock()
return
}
- }
+ heightValue := uint64(0)
+ if heightField != "" {
+ heightValue, err = record.Cnt.ValueByName(heightField)
+ if err != nil {
+ return
+ }
+ }
- frames := lt.buildFrames(record)
- lt.addLocked(frames, value, heightValue)
- lt.version.Add(1)
- lt.mu.Unlock()
+ frames := buildFrames(record, fields)
+
+ lt.mu.Lock()
+ if countField != lt.countField || heightField != lt.heightField || !slices.Equal(fields, lt.fields) {
+ lt.mu.Unlock()
+ continue
+ }
+ lt.addLocked(frames, value, heightValue)
+ lt.version.Add(1)
+ lt.mu.Unlock()
+ return
+ }
}
// Reset clears the trie so live snapshots start from a new baseline.
@@ -292,9 +308,9 @@ func eventPairToRecord(ep *event.Pair) IterRecord {
}
}
-func (lt *LiveTrie) buildFrames(record IterRecord) []string {
- frames := make([]string, 0, len(lt.fields))
- for _, fieldName := range lt.fields {
+func buildFrames(record IterRecord, fields []string) []string {
+ frames := make([]string, 0, len(fields))
+ for _, fieldName := range fields {
value, err := record.StringByName(fieldName)
if err != nil {
continue