diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-24 20:20:42 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-24 20:20:42 +0200 |
| commit | 8361fd22d45e4fbf6b24309aaa1b6d49d9010759 (patch) | |
| tree | 1aef478a8bc096acee794802b8dc7e29b32ecdb9 /internal/flamegraph/nativesvg.go | |
| parent | 81735bb46a75dce67a06e383f0703871e23b29d4 (diff) | |
flamegraph: add native svg pipeline and tests
Diffstat (limited to 'internal/flamegraph/nativesvg.go')
| -rw-r--r-- | internal/flamegraph/nativesvg.go | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/internal/flamegraph/nativesvg.go b/internal/flamegraph/nativesvg.go new file mode 100644 index 0000000..2c76a7d --- /dev/null +++ b/internal/flamegraph/nativesvg.go @@ -0,0 +1,74 @@ +package flamegraph + +import ( + "fmt" + "io" + "os" + "strings" + + "iter" +) + +type NativeSVG struct { + fields []string + countField string + config SVGConfig +} + +func NewNativeSVG(fields []string, countField string) NativeSVG { + return NativeSVG{ + fields: fields, + countField: countField, + config: defaultSVGConfig(), + } +} + +func (n NativeSVG) WriteSVGFromFile(iorDataFile string) error { + outFile := fmt.Sprintf("%s.%s-by-%s.svg", + strings.TrimSuffix(iorDataFile, ".ior.zst"), + strings.Join(n.fields, ":"), + n.countField, + ) + + iod, err := newIorDataFromFile(iorDataFile) + if err != nil { + return fmt.Errorf("read ior data: %w", err) + } + + fd, err := os.Create(outFile) + if err != nil { + return fmt.Errorf("create output %s: %w", outFile, err) + } + defer fd.Close() + + return n.WriteSVGFromIter(iod.iter(), fd) +} + +func (n NativeSVG) WriteSVGFromIter(records iter.Seq[IterRecord], w io.Writer) error { + tr := newTrie() + for record := range records { + frames, err := n.recordFrames(record) + if err != nil { + return err + } + tr.add(frames, record.Cnt.ValueByName(n.countField)) + } + tr.computeTotals() + return WriteSVG(w, tr, n.config) +} + +func (n NativeSVG) recordFrames(record IterRecord) ([]string, error) { + var frames []string + for _, fieldName := range n.fields { + value, err := record.StringByName(fieldName) + if err != nil { + return nil, fmt.Errorf("field %s: %w", fieldName, err) + } + for _, part := range strings.Split(value, ";") { + if part != "" { + frames = append(frames, part) + } + } + } + return frames, nil +} |
