diff --git a/block.md b/block.md index 07a0172..0f5b13b 100644 --- a/block.md +++ b/block.md @@ -18,7 +18,7 @@ The block profile in Go lets you analyze how much time your program spends waiti - [semacquire](https://github.com/golang/go/blob/go1.15.7/src/runtime/sema.go#L150) ( [`Mutex.Lock`](https://golang.org/pkg/sync/#Mutex.Lock), [`RWMutex.RLock`](https://golang.org/pkg/sync/#RWMutex.RLock) , [`RWMutex.Lock`](https://golang.org/pkg/sync/#RWMutex.Lock), [`WaitGroup.Wait`](https://golang.org/pkg/sync/#WaitGroup.Wait)) - [notifyListWait](https://github.com/golang/go/blob/go1.15.7/src/runtime/sema.go#L515) ( [`Cond.Wait`](https://golang.org/pkg/sync/#Cond.Wait)) -Time is only tracked when Go has to suspend the goroutine's execution by parking it into a [waiting](https://github.com/golang/go/blob/go1.15.7/src/runtime/runtime2.go#L51-L59) state. So for example a `Mutex.Lock()` operation will not show up in your profile if the lock can be aquired immediately or via a short amount of [spinning](https://en.wikipedia.org/wiki/Spinlock). +Time is only tracked when Go has to suspend the goroutine's execution by parking it into a [waiting](https://github.com/golang/go/blob/go1.15.7/src/runtime/runtime2.go#L51-L59) state. So for example a `Mutex.Lock()` operation will not show up in your profile if the lock can be acquired immediately or via a short amount of [spinning](https://en.wikipedia.org/wiki/Spinlock). The operations above are a subset of the [waiting states](https://github.com/golang/go/blob/go1.15.7/src/runtime/runtime2.go#L996-L1024) used by the Go runtime, i.e. the operations below **will not** show up in a block profile: diff --git a/examples/block-vs-mutex/main.go b/examples/block-vs-mutex/main.go index 5c0e336..d55e94b 100644 --- a/examples/block-vs-mutex/main.go +++ b/examples/block-vs-mutex/main.go @@ -20,18 +20,18 @@ func run() error { runtime.SetBlockProfileRate(1) runtime.SetMutexProfileFraction(1) - aquired := make(chan struct{}) + acquired := make(chan struct{}) var m sync.Mutex m.Lock() go func() { - <-aquired + <-acquired m.Lock() - aquired <- struct{}{} + acquired <- struct{}{} }() - aquired <- struct{}{} + acquired <- struct{}{} time.Sleep(time.Nanosecond) m.Unlock() - <-aquired + <-acquired if err := writeProfile("block"); err != nil { return err diff --git a/goroutine.md b/goroutine.md index db06827..c770c43 100644 --- a/goroutine.md +++ b/goroutine.md @@ -33,7 +33,7 @@ All Goroutine profiling available in Go requires an `O(N)` **stop-the-world** ph As a rule of thumb, applications that are extremely latency sensitive and make use of thousands of active goroutines might want to be a little careful with goroutine profiling in production. That being said, large number of goroutines, and perhaps even Go itself, might not be good idea for such applications to begin with. -Most applications that don't spawn crazy amounts of goroutines and can tolerate a few ms of ocassional extra latency should have no issues with continous goroutine profiling in production. +Most applications that don't spawn crazy amounts of goroutines and can tolerate a few ms of occasional extra latency should have no issues with continuous goroutine profiling in production. ## Goroutine Properties diff --git a/pprof.md b/pprof.md index 9726d21..093db5a 100644 --- a/pprof.md +++ b/pprof.md @@ -22,7 +22,7 @@ A picture is worth a thousand words, so below is an automatically [generated](ht profile.proto visualized -pprof's data format appears to be designed to for efficency, multiple languages and different profile types (CPU, Heap, etc.), but because of this it's very abstract and full of indirection. If you want all the details, follow the links above. If you want the **tl;dr**, keep reading: +pprof's data format appears to be designed to for efficiency, multiple languages and different profile types (CPU, Heap, etc.), but because of this it's very abstract and full of indirection. If you want all the details, follow the links above. If you want the **tl;dr**, keep reading: A pprof file contains a list of **stack traces** called *samples* that have one or more numeric **value** associated with them. For a CPU profile the value might be the CPU time duration in nanoseonds that the stack trace was observed for during profiling. For a heap profile it might be the number of bytes allocated. The **value types** themselves are described in the beginning of the file and used to populate the "SAMPLE" drop down in the pprof UI. In addition to the values, each stack trace can also include a set of **labels**. The labels are key-value pairs and can even include a unit. In Go those labels are used for [profiler labels](https://rakyll.org/profiler-labels/).