Saturday, September 30, 2017

Profiling and optimizing Go web applications

Profiling and optimizing Go web applications

Install Graphviz for generating a PDF file:

# apt-get install graphviz

Use hey as the benchmark tool:

# go get -u github.com/rakyll/hey
# hey -n 100000 -c 10 http://localhost:8080

Sample code:

package main

import (
 "fmt"
 "log"
 "net/http"
 _ "net/http/pprof" // here be dragons
)

func main() {
 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Hello World!")
 })
 log.Fatal(http.ListenAndServe(":8080", nil))
}

If your web application is using a custom mux (HTTP request multiplexer), you will need to register a few pprof HTTP endpoints manually:

package main

import (
    "net/http"
    "net/http/pprof"
)

func hiHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("hi"))
}

func main() {
    r := http.NewServeMux()
    r.HandleFunc("/", hiHandler)

    // Register pprof handlers
    r.HandleFunc("/debug/pprof/", pprof.Index)
    r.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    r.HandleFunc("/debug/pprof/profile", pprof.Profile)
    r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
    r.HandleFunc("/debug/pprof/trace", pprof.Trace)

    http.ListenAndServe(":8080", r)
}

CPU profile:

http://localhost:8080/debug/pprof/profile

Memory profile:

http://localhost:8080/debug/pprof/heap

Goroutine blocking profile:

http://localhost:8080/debug/pprof/block

To look at the holders of contended mutexes, after calling runtime.SetMutexProfileFraction in your program:

http://localhost:8080/debug/pprof/mutex

All goroutines with stack traces:

http://localhost:8080/debug/pprof/goroutine?debug=1

Take a trace:

http://localhost:8080/debug/pprof/trace

To view all available profiles, open:

http://localhost:8080/debug/pprof/

To look at a 30-second CPU profile:

# go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30
(pprof) top
(pprof) web
(pprof) exit

Note: Run go tool pprof -h 2>&1 | less for more information.

# go tool pprof -text http://localhost:8080/debug/pprof/profile?seconds=10 | tee cpu.txt

Note: output to a text file.

# go tool pprof -pdf http://localhost:8080/debug/pprof/profile?seconds=10 > cpu.pdf

Note: output to a PDF file.

# go tool pprof -tree http://localhost:8080/debug/pprof/profile?seconds=10 > cpu.txt

Note: Outputs a text rendering of call graph.

# go tool pprof -web http://localhost:8080/debug/pprof/profile?seconds=10

Note: Visualize graph through web browser.

To collect a 5-second execution trace:

# curl -o trace.out http://192.168.1.1:8080/debug/pprof/trace?seconds=10

# go tool trace -http="127.0.0.1:6060" trace.out

Note: You can run these two commands above on a client machine (e.g., Windows)

Reference:

https://golang.org/pkg/net/http/pprof/

https://blog.golang.org/2011/06/profiling-go-programs.html

http://artem.krylysov.com/blog/2017/03/13/profiling-and-optimizing-go-web-applications/

http://mmcloughlin.com/posts/your-pprof-is-showing

https://github.com/zmap

http://blog.ralch.com/tutorial/golang-performance-and-memory-analysis/

No comments: