Skip to content

Instantly share code, notes, and snippets.

@meson10
Created November 13, 2016 16:19
Show Gist options
  • Save meson10/61e9dd35616e905cda01fc474940d9b5 to your computer and use it in GitHub Desktop.
Save meson10/61e9dd35616e905cda01fc474940d9b5 to your computer and use it in GitHub Desktop.
Profiling explained
package main
import (
"fmt"
"log"
"os"
"runtime"
"runtime/pprof"
"strconv"
"sync"
"syscall"
"time"
)
func profileCPU() {
f, err := os.Create("cpu.prof")
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
if err := pprof.StartCPUProfile(f); err != nil {
fmt.Println("could not start CPU profile: ", err)
}
defer pprof.StopCPUProfile()
}
func profileMemory() {
f, err := os.Create("mem.prof")
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(f); err != nil {
fmt.Println("could not write memory profile: ", err)
}
f.Close()
}
func timevalToDuration(tv syscall.Timeval) time.Duration {
return time.Duration(tv.Nano()) * time.Nanosecond
}
func bytesToMebibytesFloat(bts uint64) float64 {
return float64(bts) / (1024 * 1024)
}
type stats struct {
numGoroutine int
allocBytes uint64
gcdelta uint32
minPause time.Duration
maxPause time.Duration
}
type sample struct {
memStats runtime.MemStats
numGoroutine int
numCPU int
}
func getSample() *sample {
s := sample{
numGoroutine: runtime.NumGoroutine(),
numCPU: runtime.NumCPU(),
}
ru := syscall.Rusage{}
if err := syscall.Getrusage(syscall.RUSAGE_SELF, &ru); err != nil {
fmt.Println("sample error", err.Error())
return nil
}
runtime.ReadMemStats(&s.memStats)
return &s
}
func getStats(cur, prev *sample) stats {
s := stats{
numGoroutine: cur.numGoroutine,
allocBytes: cur.memStats.Alloc,
}
gcdelta := cur.memStats.NumGC - prev.memStats.NumGC
if gcdelta <= 0 {
return s
}
deltaPauseTotalNs := cur.memStats.PauseTotalNs - prev.memStats.PauseTotalNs
maxPauseNs := deltaPauseTotalNs / uint64(gcdelta)
minPauseNs := deltaPauseTotalNs / uint64(gcdelta)
for i := prev.memStats.NumGC + 1; i <= cur.memStats.NumGC; i++ {
pause := cur.memStats.PauseNs[(i+255)%256]
if pause > maxPauseNs {
maxPauseNs = pause
}
if pause < minPauseNs {
minPauseNs = pause
}
}
s.gcdelta = gcdelta
s.minPause = time.Duration(minPauseNs) * time.Nanosecond
s.maxPause = time.Duration(maxPauseNs) * time.Nanosecond
return s
}
func perf(fn func()) {
s1 := getSample()
fn()
s2 := getSample()
fmt.Printf("%+v\n", getStats(s1, s2))
}
// AbstractInh is a function to demostrate abstract inheritence
func main() {
var wg sync.WaitGroup
for y := 0; y < 3; y++ {
for x := 0; x < 2; x++ {
wg.Add(1)
go func(num int) {
defer wg.Done()
time.Sleep(2 * time.Second)
fmt.Println("Hello", strconv.Itoa(num))
time.Sleep(time.Duration(num) * time.Second)
}(x + y)
}
}
perf(func() {
wg.Wait()
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment