github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/convert/pprof/decoder.go (about) 1 package pprof 2 3 import ( 4 "bufio" 5 "compress/gzip" 6 "fmt" 7 "github.com/pyroscope-io/pyroscope/pkg/convert/pprof/streaming" 8 "io" 9 10 "github.com/pyroscope-io/pyroscope/pkg/storage/tree" 11 ) 12 13 func Decode(r io.Reader, p *tree.Profile) error { 14 br := bufio.NewReader(r) 15 header, err := br.Peek(2) 16 if err != nil { 17 return fmt.Errorf("failed to read pprof profile header: %w", err) 18 } 19 if header[0] == 0x1f && header[1] == 0x8b { 20 gzipr, err := gzip.NewReader(br) 21 if err != nil { 22 return fmt.Errorf("failed to create pprof profile zip reader: %w", err) 23 } 24 r = gzipr 25 defer gzipr.Close() 26 } else { 27 r = br 28 } 29 buf := streaming.PPROFBufPool.Get() 30 defer streaming.PPROFBufPool.Put(buf) 31 if _, err = io.Copy(buf, r); err != nil { 32 return err 33 } 34 return p.UnmarshalVT(buf.Bytes()) 35 } 36 37 func DecodePool(r io.Reader, fn func(*tree.Profile) error) error { 38 p := tree.ProfileFromVTPool() 39 defer p.ReturnToVTPool() 40 p.Reset() 41 if err := Decode(r, p); err != nil { 42 return err 43 } 44 return fn(p) 45 }