github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/convert/profile_extra_bench_test.go (about)

     1  package convert
     2  
     3  import (
     4  	"bytes"
     5  	"compress/gzip"
     6  	"fmt"
     7  	"os"
     8  	"testing"
     9  
    10  	"github.com/pyroscope-io/pyroscope/pkg/agent/spy"
    11  	"github.com/pyroscope-io/pyroscope/pkg/storage/tree"
    12  )
    13  
    14  func BenchmarkProfile_Get(b *testing.B) {
    15  	buf, _ := os.ReadFile("testdata/cpu.pprof")
    16  	g, _ := gzip.NewReader(bytes.NewReader(buf))
    17  	p, _ := ParsePprof(g)
    18  	noop := func(labels *spy.Labels, name []byte, val int) error { return nil }
    19  	b.ResetTimer()
    20  
    21  	b.Run("ByteBufferPool", func(b *testing.B) {
    22  		for i := 0; i < b.N; i++ {
    23  			_ = p.Get("samples", noop)
    24  		}
    25  	})
    26  }
    27  
    28  // parse emulates the parsing work needed to write profiles, without the writing part.
    29  func parse(p *tree.Profile) int {
    30  	var b bytes.Buffer
    31  	for _, s := range p.Sample {
    32  		for i := len(s.LocationId) - 1; i >= 0; i-- {
    33  			loc, ok := tree.FindLocation(p, s.LocationId[i])
    34  			if !ok {
    35  				continue
    36  			}
    37  			for j := len(loc.Line) - 1; j >= 0; j-- {
    38  				fn, found := tree.FindFunction(p, loc.Line[j].FunctionId)
    39  				if !found {
    40  					continue
    41  				}
    42  				if b.Len() > 0 {
    43  					_ = b.WriteByte(';')
    44  				}
    45  				_, _ = b.WriteString(p.StringTable[fn.Name])
    46  			}
    47  		}
    48  	}
    49  	return len(b.Bytes())
    50  }
    51  
    52  // parseWithCache is like parse, but locations and functions are tabled first.
    53  func parseWithCache(p *tree.Profile) int {
    54  	finder := tree.NewFinder(p)
    55  	var b bytes.Buffer
    56  	for _, s := range p.Sample {
    57  		for i := len(s.LocationId) - 1; i >= 0; i-- {
    58  			loc, ok := finder.FindLocation(s.LocationId[i])
    59  			if !ok {
    60  				continue
    61  			}
    62  			for j := len(loc.Line) - 1; j >= 0; j-- {
    63  				fn, ok := finder.FindFunction(loc.Line[j].FunctionId)
    64  				if !ok {
    65  					continue
    66  				}
    67  				if b.Len() > 0 {
    68  					_ = b.WriteByte(';')
    69  				}
    70  				_, _ = b.WriteString(p.StringTable[fn.Name])
    71  			}
    72  		}
    73  	}
    74  	return len(b.Bytes())
    75  }
    76  
    77  func BenchmarkProfile_ParseNoCache(b *testing.B) {
    78  	buf, _ := os.ReadFile("testdata/cpu.pprof")
    79  	p, _ := ParsePprof(bytes.NewReader(buf))
    80  
    81  	b.ResetTimer()
    82  
    83  	b.Run(fmt.Sprintf("Locations: %d, functions %d", len(p.Location), len(p.Function)), func(b *testing.B) {
    84  		for i := 0; i < b.N; i++ {
    85  			_ = parse(p)
    86  		}
    87  	})
    88  }
    89  
    90  func BenchmarkProfile_ParseWithCache(b *testing.B) {
    91  	buf, _ := os.ReadFile("testdata/cpu.pprof")
    92  	p, _ := ParsePprof(bytes.NewReader(buf))
    93  
    94  	b.ResetTimer()
    95  
    96  	b.Run(fmt.Sprintf("Locations: %d, functions %d", len(p.Location), len(p.Function)), func(b *testing.B) {
    97  		for i := 0; i < b.N; i++ {
    98  			_ = parseWithCache(p)
    99  		}
   100  	})
   101  }
   102  
   103  func BenchmarkProfile_ParseNoCache_Big(b *testing.B) {
   104  	buf, _ := os.ReadFile("testdata/cpu-big.pprof")
   105  	p, _ := ParsePprof(bytes.NewReader(buf))
   106  
   107  	b.ResetTimer()
   108  
   109  	b.Run(fmt.Sprintf("Locations: %d, functions %d", len(p.Location), len(p.Function)), func(b *testing.B) {
   110  		for i := 0; i < b.N; i++ {
   111  			_ = parse(p)
   112  		}
   113  	})
   114  }
   115  
   116  func BenchmarkProfile_ParseWithCache_Big(b *testing.B) {
   117  	buf, _ := os.ReadFile("testdata/cpu-big.pprof")
   118  	p, _ := ParsePprof(bytes.NewReader(buf))
   119  
   120  	b.ResetTimer()
   121  
   122  	b.Run(fmt.Sprintf("Locations %d, functions %d", len(p.Location), len(p.Function)), func(b *testing.B) {
   123  		for i := 0; i < b.N; i++ {
   124  			_ = parseWithCache(p)
   125  		}
   126  	})
   127  }