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  }