Profiling Most Relevant Sections of the Application

Long-running applications are not always busy doing work. In case of, for instance, web, serverless or microservice applications, the work is done on every request and the processes are idle the rest of the time. Similarly, if the program is processing messages from the queue, it may be idle when it is waiting for messages.

In order to profile those specific activity intervals of the program in a long-running application, a profiler should be started prior to the activity begin, which is not always automatically possible.

StackImpact agents start and stop profilers automatically during the profiling cycle, typically a couple of minutes long, at the end of which the profiles are ready to be reported. The goal of the profiler starter algorithm is to increase the probability of profiling the program when it is doing relevant work. This works well for programs with equally distributed workloads, but is not optimal for programs where profiling some sections is more important than others.

For these cases the agents provide agent.Profile() method. Calling it will tell the agent about a relevant section of the program execution. The agent.Profile() call will not always start and stop profilers, since the overhead constraints on how many times and for how long each profiler can be active have a higher priority. The decision of what profiler to start, e.g. CPU profiler, memory allocation profiler, blocking or async call profiler, is made by the agent.

Using workload profiling will not disable automatic profiling. Both may activate the profilers as long as the overhead limit is not reached for the profiling cycle.

Here is an example of Go application, which instructs the agent when to start and stop profiling:

package main

import (
	"fmt"
	"net/http"

	"github.com/stackimpact/stackimpact-go"
)

var agent *stackimpact.Agent

func handler(w http.ResponseWriter, r *http.Request) {
	span := agent.Profile(")
	defer span.Stop()

	fmt.Fprintf(w, "Hello world!")
}

func main() {
	agent = stackimpact.Start(stackimpact.Options{
		AgentKey: "agent key here",
		AppName: "My Go App",
	})

	http.HandleFunc("/", handler) 
	http.ListenAndServe(":8080", nil)
}

Helper wrappers for HTTP handlers are available as well.

See agents’ Github repositories for more information on workload profiling support and usage.