Upsun User Documentation

Continuous profiling for Go

Try Upsun for 15 days
After that, enjoy the same, game-changing Upsun features for less with the First Project Incentive!ยน A monthly $19 perk!
ยนTerms and conditions apply
Activate your 15-day trial

Feature Availability

By default, Upsun offers 15 minutes of continuous profiling per project and for free. To get 30 days of continuous profiling per project and for a fixed fee, upgrade to the Continuous Profiling add-on.

Continuous profiling on Upsun Anchor to this heading

Upsun Continuous Profiler is powered by Blackfire. It is available directly from the Console under the Profiling tab of your environments.

The GO continuous profiling is currently made across 6 dimensions:

  • Allocations: Number of objects allocated
  • Allocated Memory: Number of bytes allocated
  • CPU: Time spent running on the CPU
  • Goroutines: Number of goroutines (both on-CPU and off-CPU)
  • Heap Live Objects: Number of objects allocated that are not yet garbage collected
  • Heap Live Size: Number of bytes allocated that are not yet garbage collected

The default sampling frequency is 100 Hz. This means the Go continuous profiler is collecting information 100 times per second.

Prerequisites Anchor to this heading

Upsun Continuous Profiler requires Go >=1.18.

Installation Anchor to this heading

Get the Blackfire Continuous Profiler Go library:

go get github.com/blackfireio/go-continuous-profiling

Go continuous profiler API Anchor to this heading

The Go continuous profiler API has two functions:

func Start(opts ...Option) error {}
func Stop() {}

func Start(opts ...Option) error Anchor to this heading

Start starts the continuous profiler probe. It collects profiling information and uploads it to the Blackfire Agent periodically.

profiler.Start(
       profiler.WithCPUDuration(3 * time.Second),
       profiler.WithCPUProfileRate(1000),
       profiler.WithProfileTypes(profiler.CPUProfile, profiler.HeapProfile, profiler.GoroutineProfile),
       profiler.WithLabels({
            "key1": "value1",
            "key2": "value2",
       }),
       profiler.WithUploadTimeout(5 * time.Second),
)
defer profiler.Stop()

The Start function accepts the following options:

  • WithCPUDuration: specifies the length at which to collect CPU profiles. The default is 45 seconds. Can also be set via the environment variable BLACKFIRE_CONPROF_CPU_DURATION.

  • WithCPUProfileRate: sets the CPU profiling rate in Hz (number of samples per second). The default is defined by the Go runtime as 100 Hz. Can also be set via the environment variable BLACKFIRE_CONPROF_CPU_PROFILERATE.

  • WithProfileTypes: sets the profiler types. Multiple profile types can be set (profiler.CPUProfile, profiler.HeapProfile, profiler.GoroutineProfile). The default is Profiler.CPUProfile.

  • WithLabels: sets custom labels specific to the profile payload that is sent.

  • WithUploadTimeout: sets the upload timeout of the message that is sent to the Blackfire Agent. The default is 10 seconds. Can also be set via the environment variable BLACKFIRE_CONPROF_UPLOAD_TIMEOUT.

There is also some additional configuration that can be done using environment variables:

  • BLACKFIRE_LOG_FILE: Sets the log file. The default is logging to stderr.

  • BLACKFIRE_LOG_LEVEL: Sets the log level. The default is logging only errors.

func Stop() Anchor to this heading

Stops the continuous profiling probe.

An example application Anchor to this heading

  1. Get the Blackfire Continuous Profiler Go library
go get github.com/blackfireio/go-continuous-profiling
  1. Save the following code as main.go and run as follows:
go run main.go
package main

import (
	"crypto/md5"
	"encoding/hex"
	"io"
	"time"

	profiler "github.com/blackfireio/go-continuous-profiling"
)

func doSomethingCpuIntensive() {
	md5Hash := func(s string) string {
		h := md5.New()
		io.WriteString(h, s)
		return hex.EncodeToString(h.Sum(nil))
	}
	for i := 0; i < 1_000_000; i++ {
		md5Hash("UpsunIsCoolAndSoAreYou")
	}
}

func main() {
	err := profiler.Start(
		profiler.WithAppName("my-app"),
	)
	if err != nil {
		panic("Error while starting Profiler")
	}
	defer profiler.Stop()

	for i := 0; i < 15; i++ {
		doSomethingCpuIntensive()

		time.Sleep(1 * time.Second)
	}
}

Is this page helpful?