Initial work on new guide
@ -4,6 +4,7 @@ Hey there 👋🏻, I'm [felixge](https://github.com/felixge) and I've just star
|
|||||||
|
|
||||||
I found that Go has a lot of profilers and there are many tools for looking at the data, but that there is very little information on what any of it means. So in order to make sure that I know what I'm talking about, I've started to research the existing profilers and how they work. This repository is my attempt to summarize my findings in the hope that it might be useful to others.
|
I found that Go has a lot of profilers and there are many tools for looking at the data, but that there is very little information on what any of it means. So in order to make sure that I know what I'm talking about, I've started to research the existing profilers and how they work. This repository is my attempt to summarize my findings in the hope that it might be useful to others.
|
||||||
|
|
||||||
|
- [The Busy Developers's Guide to Go Profiling, Tracing and Observability](./guide/README.md)
|
||||||
- [pprof tool & format](./pprof.md): Describes the pprof tool and the binary data format for storing profiles.
|
- [pprof tool & format](./pprof.md): Describes the pprof tool and the binary data format for storing profiles.
|
||||||
- [Stack Traces](./stack-traces.md): An in-depth look at stack traces in Go which are a load bearing subsystem for profiling.
|
- [Stack Traces](./stack-traces.md): An in-depth look at stack traces in Go which are a load bearing subsystem for profiling.
|
||||||
- [Goroutine Profiling](./goroutine.md): Allows you to get a list of all active goroutines and what they're currently doing.
|
- [Goroutine Profiling](./goroutine.md): Allows you to get a list of all active goroutines and what they're currently doing.
|
||||||
|
BIN
examples/guide/main
Executable file
12
examples/guide/main.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
start := time.Now()
|
||||||
|
for time.Since(start) < time.Second {
|
||||||
|
}
|
||||||
|
//time.Sleep(time.Second)
|
||||||
|
}
|
27
examples/guide/main2.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"runtime/trace"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
trace.Start(os.Stdout)
|
||||||
|
defer trace.Stop()
|
||||||
|
|
||||||
|
go b()
|
||||||
|
a()
|
||||||
|
}
|
||||||
|
|
||||||
|
func a() {
|
||||||
|
start := time.Now()
|
||||||
|
for time.Since(start) < time.Second {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func b() {
|
||||||
|
start := time.Now()
|
||||||
|
for time.Since(start) < time.Second {
|
||||||
|
}
|
||||||
|
}
|
19
examples/guide/main3.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"runtime/trace"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
trace.Start(os.Stderr)
|
||||||
|
defer trace.Stop()
|
||||||
|
|
||||||
|
res, err := http.Get("https://example.org/")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%d\n", res.StatusCode)
|
||||||
|
}
|
BIN
examples/guide/trace.bin
Normal file
512
guide.excalidraw
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
{
|
||||||
|
"type": "excalidraw",
|
||||||
|
"version": 2,
|
||||||
|
"source": "https://excalidraw.com",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "ellipse",
|
||||||
|
"version": 439,
|
||||||
|
"versionNonce": 99598167,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "OkVhsngC1W_qO9sNi0ZKD",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 712.3327975802952,
|
||||||
|
"y": 1064.5428764974185,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#e69f00",
|
||||||
|
"width": 392.02349853515625,
|
||||||
|
"height": 388.1683520208971,
|
||||||
|
"seed": 1622389102,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 333,
|
||||||
|
"versionNonce": 915293529,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "zi6i3xeoTlw2jmvkvo0MH",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 843.216566297743,
|
||||||
|
"y": 1387.2014024522568,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"width": 148,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1862147767,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Goroutine Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ellipse",
|
||||||
|
"version": 447,
|
||||||
|
"versionNonce": 351741913,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "YREBQWDaV41cof7PNs-br",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 717.6362750700704,
|
||||||
|
"y": 1152.5910203721785,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#56b4e9",
|
||||||
|
"width": 218.25456981428613,
|
||||||
|
"height": 216.10826137312208,
|
||||||
|
"seed": 2138441529,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 275,
|
||||||
|
"versionNonce": 2133733945,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "GLANOsn9G3AgWIiZsTm0k",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 772.6275160047743,
|
||||||
|
"y": 1313.185594346788,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"width": 105,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1548483929,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Block Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ellipse",
|
||||||
|
"version": 584,
|
||||||
|
"versionNonce": 968102423,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "4JSZd_8EU30-i5ZTcEMII",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 756.3474011055642,
|
||||||
|
"y": 1153.7242601182722,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "yellow",
|
||||||
|
"width": 143.066548976275,
|
||||||
|
"height": 141.65963712110846,
|
||||||
|
"seed": 714197463,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 371,
|
||||||
|
"versionNonce": 184386329,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "9INmL5p1bzQ4ybvAY_FvP",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 771.523206922743,
|
||||||
|
"y": 1215.219285753038,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"width": 114,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 2132545303,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Mutex Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ellipse",
|
||||||
|
"version": 737,
|
||||||
|
"versionNonce": 1295947127,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "WowgALfO30J7LlVnLjWSY",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 951.207475970678,
|
||||||
|
"y": 1156.7638086620884,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#cc79a7",
|
||||||
|
"width": 140.0686567283485,
|
||||||
|
"height": 138.69122604941987,
|
||||||
|
"seed": 460035961,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 231,
|
||||||
|
"versionNonce": 107984889,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "Y_QmsQGgj_OEe1xJWA90D",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 976.2918531629771,
|
||||||
|
"y": 1217.2686330105935,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"width": 94,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 513434745,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "CPU Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "center",
|
||||||
|
"verticalAlign": "middle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "arrow",
|
||||||
|
"version": 836,
|
||||||
|
"versionNonce": 1098090263,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "LQL7eklipWPJw7N6IV0k3",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 1134.1059168640527,
|
||||||
|
"y": 1337.203653024999,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 144.83075681630953,
|
||||||
|
"height": 1.2338944467890087,
|
||||||
|
"seed": 1019757362,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "r5QpngwDotW31qiS-84QZ",
|
||||||
|
"focus": 0.09220703124999852,
|
||||||
|
"gap": 9.483194464072312
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-144.83075681630953,
|
||||||
|
1.2338944467890087
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 352,
|
||||||
|
"versionNonce": 634511609,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "r5QpngwDotW31qiS-84QZ",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 1143.589111328125,
|
||||||
|
"y": 1301.7774454752603,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 337,
|
||||||
|
"height": 75,
|
||||||
|
"seed": 529830642,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [
|
||||||
|
"LQL7eklipWPJw7N6IV0k3"
|
||||||
|
],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Untracked Off-CPU Waiting Time\ne.g. I/O, Syscalls (unless on-CPU),\nSleep, Scheduler Backlog, etc.",
|
||||||
|
"baseline": 68,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "arrow",
|
||||||
|
"version": 242,
|
||||||
|
"versionNonce": 665524055,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "5nPCmBZUtW-sy9jSYVrnr",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 677.2958755453465,
|
||||||
|
"y": 1303.3024483091128,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"width": 71.47162543402794,
|
||||||
|
"height": 0.00248566351797308,
|
||||||
|
"seed": 2009323314,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "qGeURJQ0SK2OA3yANfDzs",
|
||||||
|
"focus": -0.194383063549796,
|
||||||
|
"gap": 4.673326280381957
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
71.47162543402794,
|
||||||
|
0.00248566351797308
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "arrow",
|
||||||
|
"version": 501,
|
||||||
|
"versionNonce": 36028281,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "Zw3pCq23-wlOAG9qzCGEn",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 675.6552315783205,
|
||||||
|
"y": 1195.36276817402,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"width": 124.66751299914404,
|
||||||
|
"height": 0,
|
||||||
|
"seed": 1500343342,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "xX3KMMOFeoWOYKAxIHlez",
|
||||||
|
"focus": -0.08419197923809406,
|
||||||
|
"gap": 9.55796866599428
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
124.66751299914404,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 345,
|
||||||
|
"versionNonce": 630725049,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "xX3KMMOFeoWOYKAxIHlez",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 459.0972629123262,
|
||||||
|
"y": 1183.9151679144961,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 207,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1832387353,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [
|
||||||
|
"kBCBSYv6myf_GunPogGXE",
|
||||||
|
"Zw3pCq23-wlOAG9qzCGEn"
|
||||||
|
],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Off-CPU Mutex Wait",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 203,
|
||||||
|
"versionNonce": 1463938233,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "qGeURJQ0SK2OA3yANfDzs",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 362.6225492649645,
|
||||||
|
"y": 1293.2277312816586,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"width": 310,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1013246894,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [
|
||||||
|
"5nPCmBZUtW-sy9jSYVrnr"
|
||||||
|
],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Off-CPU Mutex + Channel Wait",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "arrow",
|
||||||
|
"version": 1555,
|
||||||
|
"versionNonce": 756641785,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "kBCBSYv6myf_GunPogGXE",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 1136.375882316133,
|
||||||
|
"y": 1201.148154782728,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 73.68763800422926,
|
||||||
|
"height": 0,
|
||||||
|
"seed": 1548243191,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "o7HqqenoMX9Jbq_HhYpVp",
|
||||||
|
"focus": -0.11262693564109214,
|
||||||
|
"gap": 14.676232378519217
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-73.68763800422926,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 426,
|
||||||
|
"versionNonce": 669605623,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "o7HqqenoMX9Jbq_HhYpVp",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 1151.0521146946521,
|
||||||
|
"y": 1187.2403180872143,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"width": 293,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 2043685486,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [
|
||||||
|
"kBCBSYv6myf_GunPogGXE"
|
||||||
|
],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "On-CPU User and Kernel Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"appState": {
|
||||||
|
"gridSize": null,
|
||||||
|
"viewBackgroundColor": "#ffffff"
|
||||||
|
}
|
||||||
|
}
|
11
guide/Makefile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.PHONY: scheduler.gif
|
||||||
|
scheduler.gif:
|
||||||
|
convert -delay 100 scheduler.*.png scheduler.gif
|
||||||
|
|
||||||
|
.PHONY: stack.gif
|
||||||
|
stack.gif:
|
||||||
|
convert -delay 200 stack*.png stack.gif
|
||||||
|
|
||||||
|
.PHONY: heap-gc.gif
|
||||||
|
heap-gc.gif:
|
||||||
|
convert -delay 200 heap-gc.*.png heap-gc.gif
|
144
guide/README.md
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
⬅ [Index of all go-profiler-notes](../README.md)
|
||||||
|
# The Busy Developers's Guide to Go Profiling, Tracing and Observability
|
||||||
|
|
||||||
|
- **[Introduction](#introduction):** [Read This](#read-this) · [Mental Model for Go](#mental-model-for-go) · Profiling vs Tracing
|
||||||
|
- **Use Cases:** Reduce Costs · Reduce Latency · Memory Leaks · Program Hanging · Outages
|
||||||
|
- **Go Profilers**: CPU · Memory · Block · Mutex · Goroutine · ThreadCreate
|
||||||
|
- **Viewing Profiles**: Command Line · Flamegraph · Webgraph
|
||||||
|
- **Go Execution Tracer:** Timeline View · Derive Profiles
|
||||||
|
- **Other Tools:** time · perf · bpftrace
|
||||||
|
- **Advanced Topics:** Assembly · Stack Traces
|
||||||
|
- **Datadog Products:** Continuous Profiler · APM (Distributed Tracing)
|
||||||
|
|
||||||
|
🚧 This document is a work in progress. All sections above will become clickable links over time. Follow me [on twitter](https://twitter.com/felixge) for updates.
|
||||||
|
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
## Read This
|
||||||
|
|
||||||
|
This is a practical guide aimed at busy gophers interested in improving their programs using profiling and tracing. If you're not well versed in the internals of Go, it is recommended that you read the entire introduction first. After that you should feel free to jump to any section you are interested in.
|
||||||
|
## Mental Model for Go
|
||||||
|
|
||||||
|
It is possible to become quite proficient in writing Go code without understanding how the language works under the hood. But when it comes to performance and debugging, you'll hugely benefit from having a mental model of the internals. Therefore we'll begin with laying out a rudimentary model of Go below. This model should be good enough to allow you to avoid the most common mistakes, but [all models are wrong](https://en.wikipedia.org/wiki/All_models_are_wrong), so you are encouraged to seek out more in-depth material to tackle harder problems in the future.
|
||||||
|
|
||||||
|
Go's primary job is to multiplex and abstract hardware resources, similar to an operating system. This is generally accomplished using two major abstractions:
|
||||||
|
|
||||||
|
1. **Goroutine Scheduler:** Manages how your code is being executed on the CPUs of your system.
|
||||||
|
2. **Garbage Collector:** Provides virtual memory that is automatically freed as needed.
|
||||||
|
|
||||||
|
|
||||||
|
### Goroutine Scheduler
|
||||||
|
|
||||||
|
Let's talk about the scheduler first using the example below:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
res, err := http.Get("https://example.org/")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%d\n", res.StatusCode)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we have a single goroutine, let's call it `G1`, that runs the `main` function. The picture below shows a simplified timeline of how this goroutine might execute on a single CPU. Initially `G1` is running on the CPU to prepare the http request. Then the CPU becomes idle as the goroutine has to wait for the network. And finally it gets scheduled onto the CPU again to print out the status code.
|
||||||
|
|
||||||
|
<img src="./timeline.png" width=600/>
|
||||||
|
|
||||||
|
From the scheduler's perspective, the program above executes like shown below. At first `G1` is `Executing` on `CPU 1`. Then the goroutine is taken off the CPU while `Waiting` for the network. Once the scheduler notices that the network has replied (using non-blocking I/O, similar to to Node.js), it marks the goroutine as `Runnable`. And as soon as a CPU core becomes available, the goroutine starts `Executing` again. In our case all cores are available, so `G1` can go back to `Executing` the `fmt.Printf()` function on one of the CPUs immediately without spending any time in the `Runnable` state.
|
||||||
|
|
||||||
|
<img src="./scheduler.gif" width=400/>
|
||||||
|
|
||||||
|
Most of the time, Go programs are running multiple goroutines, so you will have a few goroutines `Executing` on some of the CPU cores, a large number of goroutines `Waiting` for various reasons, and ideally no goroutines `Runnable` unless your program exhibits very high CPU load. An example of this can be seen below.
|
||||||
|
|
||||||
|
<img src="./scheduler-complete.png" width=600/>
|
||||||
|
|
||||||
|
Of course the model above glosses over many details. In reality it's turtles all the way down, and the Go scheduler works on top of threads managed by the operating system, and even CPUs themselves are capable of hyper-threading which can be seen as a form of scheduling. So if you're interested, feel free to continue down this rabbit hole via Ardan labs series on [Scheduling in Go](https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part1.html) or similar material.
|
||||||
|
|
||||||
|
However, the model above should be sufficient to understand the remainder of this guide. In particular it should become clear that the time measured by the various Go profilers is essentially the time your goroutines are spending in the `Executing` and `Waiting` states as illustrated by the diagram below.
|
||||||
|
|
||||||
|
<img src="./profiler-venn.png" width=800/>
|
||||||
|
|
||||||
|
### Garbage Collector
|
||||||
|
|
||||||
|
The other major abstraction in Go is the garbage collector. In languages like C, the programmer needs to manually deal with allocating and releasing memory using `malloc()` and `free()`. This offers great control, but turns out to be very error prone in practice. A garbage collector can reduce this burden, but the automatic management of memory can easily become a performance bottleneck. This section of the guide will present a simple model for Go's GC that should be useful for identifying and optimizing memory management related problems.
|
||||||
|
|
||||||
|
#### The Stack
|
||||||
|
|
||||||
|
Let's start with the basics. Go can allocate memory in one of two places, the stack or the heap. Each goroutine has its own stack which is a contiguous area of memory. Additionally there is a big area of memory shared between goroutines that is called the heap. This can be seen in the picture below.
|
||||||
|
|
||||||
|
<img src="./heap-simple.png" width=650/>
|
||||||
|
|
||||||
|
When a function calls another function it gets its own section on the stack called a stack frame where it can place things like local variables. A stack pointer is used to identify the next free spot in the frame. When a function returns, the data from the last frame is discarded by simply moving the stack pointer back to end of the previous frame. The frame's data itself can linger on the stack, and gets overwritten by the next function call. This is very simple and efficient as Go doesn't have to keep track of each variable.
|
||||||
|
|
||||||
|
To make this a little more intuitive, let's look at the example below:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
sum := 0
|
||||||
|
sum = add(23, 42)
|
||||||
|
fmt.Println(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we have a `main()` function that starts out by reserving some space on the stack for the variable `sum`. When the `add()` function gets called, it gets its own frame to hold the local `a` and `b` parameters. Once the `add()` returns, its data is discarded by moving the stack pointer back to the end of the `main()` function's frame, and the `sum` variable gets updated with the result. Meanwhile the old values of `add()` linger beyond the stack pointer to be overwritten by the next function call. Below is a visualization of this process:
|
||||||
|
|
||||||
|
<img src="./stack.gif" width=400/>
|
||||||
|
|
||||||
|
The example above is highly simplified and omits many details around return values, frame pointers, return addresses and function inlining. In fact, as of Go 1.17, the program above may not even need any space on the stack as the small amount of data can be managed using CPU registers by the compiler. But that's okay. This model should still give you a reasonable intuition for the way non-trivial Go programs allocate and discard local variables on the stack.
|
||||||
|
|
||||||
|
One thing you might wonder at this point is what happens if you run out of space on the stack. In languages like C this would cause a stack overflow error. Go on the other hand automatically deals with this problem by making a copy of the stack that's twice as big. This allows goroutines to start out with very small, typically 2 KiB stacks, and is one of the key ingredients for [making goroutines more scalable](https://golang.org/doc/faq#goroutines) than operating system threads.
|
||||||
|
|
||||||
|
Another aspect of the stack is how it's involved in creating stack traces. This is a bit more advanced, but if you're interested check out the [Stack Traces in Go](../stack-traces.md) document in this repo.
|
||||||
|
#### The Heap
|
||||||
|
|
||||||
|
Stack allocations are great, but there are many situations where Go can't utilize them. The most common one is returning a pointer to a local variable of a function. This can be seen in this modified version of our `add()` example from above:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
fmt.Println(*add(23, 42))
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(a, b int) *int {
|
||||||
|
sum := a + b
|
||||||
|
return &sum
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Normally Go would be able to allocate the `sum` variable inside of the `add()` function on the stack. But as we've learned, this data gets discarded when the `add()` function returns. So in order to safely return a `&sum` pointer, Go has to allocate the memory for it from outside of the stack. And that's where the heap comes in.
|
||||||
|
|
||||||
|
The heap is used for storing memory that might outlive the function that creates it, as well as for any data that is shared between goroutines using pointers. However, this raises the question of how this memory gets freed. Because unlike stack allocations, heap allocations can't be discarded when the function that created them returns.
|
||||||
|
|
||||||
|
Go solves this problem using its built-in garbage collector. The details of its implementation are very complex, but from a birds eye view, it keeps track of your memory as shown in the picture below. Here you can see three goroutines that have pointers to green allocations on the heap. Some of these allocations also have pointers to other allocations shown in green. Additionally there are grey allocations that may point to the green allocations or each other, but they are not referenced by a green allocation themselves. Those allocations were once reachable, but are now considered to be garbage. This can happen if the function that allocated their pointers on the stack returned, or their value was overwritten. The GC is responsible for automatically identifying and freeing those allocations.
|
||||||
|
|
||||||
|
<img src="./heap-gc.gif" width=650/>
|
||||||
|
|
||||||
|
Performing GC involves a lot of expensive graph traversal and cache thrashing. It even requires regular stop-the-world phases that halt the execution of your entire program. Luckily recent versions of Go have gotten this down to fractions of a millisecond, but much of the remaining overhead is inherent to any GC. In fact, it's not uncommon that 20-30% of a Go program's execution are spend on memory management.
|
||||||
|
|
||||||
|
Generally speaking the costs of GC is proportional to the amount of heap allocations your program performs. So when it comes to optimizing the memory related overhead of your program, the mantra is:
|
||||||
|
|
||||||
|
- **Reduce**: Try to to turn heap allocations into stack allocations or avoid them alltogether.
|
||||||
|
- **Reuse:** Reuse heap allocations rather than replacing them with new ones.
|
||||||
|
- **Recycle:** Some heap allocations can't be avoided. Let the GC recycle them and focus on other issues.
|
||||||
|
|
||||||
|
As with the previous mental model in this guide, everything above is an extremely simplified view of reality. But hopefully it will be good enough to make sense out of the remainder of this guide, and inspire you to read more articles on the subject. One article you should definitely read is [Getting to Go: The Journey of Go's Garbage Collector](https://go.dev/blog/ismmkeynote) which gives you a good idea of how Go's GC has advanced over the years, and the pace at which it is improving.
|
||||||
|
|
||||||
|
# Disclaimers
|
||||||
|
|
||||||
|
I'm [felixge](https://github.com/felixge) and work at [Datadog](https://www.datadoghq.com/) on [Continuous Profiling](https://www.datadoghq.com/product/code-profiling/) for Go. You should check it out. We're also [hiring](https://www.datadoghq.com/jobs-engineering/#all&all_locations) : ).
|
||||||
|
|
||||||
|
The information on this page is believed to be correct, but no warranty is provided. Feedback is welcome!
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- Heap: Maybe a good article to link: https://medium.com/@ankur_anand/a-visual-guide-to-golang-memory-allocator-from-ground-up-e132258453ed
|
||||||
|
- GC Cost: O(N) with regards to live allocations on the heap containing pointers.
|
||||||
|
- Each pointer slot in an allocation has a cost! Even nil pointers.
|
||||||
|
- Reducing Costs: Talk about CPU, Memory and Networking. Is it possible to profile the latter?
|
||||||
|
|
||||||
|
-->
|
9674
guide/guide.excalidraw
Normal file
BIN
guide/heap-gc.1.png
Normal file
After Width: | Height: | Size: 564 KiB |
BIN
guide/heap-gc.2.png
Normal file
After Width: | Height: | Size: 486 KiB |
BIN
guide/heap-gc.gif
Normal file
After Width: | Height: | Size: 624 KiB |
BIN
guide/heap-simple.png
Normal file
After Width: | Height: | Size: 334 KiB |
28
guide/heap.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
sum int32
|
||||||
|
wg = &sync.WaitGroup{}
|
||||||
|
)
|
||||||
|
|
||||||
|
wg.Add(2)
|
||||||
|
go add(&sum, 23, wg)
|
||||||
|
go add(&sum, 42, wg)
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
fmt.Println(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(dst *int32, delta int32, wg *sync.WaitGroup) {
|
||||||
|
atomic.AddInt32(dst, delta)
|
||||||
|
wg.Done()
|
||||||
|
}
|
BIN
guide/heap.png
Normal file
After Width: | Height: | Size: 247 KiB |
16
guide/heap2.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(*add(23, 42))
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(a, b int) *int {
|
||||||
|
sum := a + b
|
||||||
|
return &sum
|
||||||
|
}
|
BIN
guide/profiler-venn.png
Normal file
After Width: | Height: | Size: 381 KiB |
BIN
guide/scheduler-complete.png
Normal file
After Width: | Height: | Size: 366 KiB |
BIN
guide/scheduler.1.png
Normal file
After Width: | Height: | Size: 143 KiB |
BIN
guide/scheduler.2.png
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
guide/scheduler.3.png
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
guide/scheduler.4.png
Normal file
After Width: | Height: | Size: 143 KiB |
BIN
guide/scheduler.gif
Normal file
After Width: | Height: | Size: 154 KiB |
BIN
guide/stack.gif
Normal file
After Width: | Height: | Size: 230 KiB |
15
guide/stack.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sum := 0
|
||||||
|
sum = add(23, 42)
|
||||||
|
fmt.Println(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
}
|
BIN
guide/stack1.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
guide/stack2.png
Normal file
After Width: | Height: | Size: 155 KiB |
BIN
guide/stack3.png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
guide/timeline.png
Normal file
After Width: | Height: | Size: 206 KiB |
BIN
hello.trace
Normal file
852
profilers.excalidraw
Normal file
@ -0,0 +1,852 @@
|
|||||||
|
{
|
||||||
|
"type": "excalidraw",
|
||||||
|
"version": 2,
|
||||||
|
"source": "https://excalidraw.com",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "ellipse",
|
||||||
|
"version": 401,
|
||||||
|
"versionNonce": 2058151026,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "OkVhsngC1W_qO9sNi0ZKD",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 626.0372924804688,
|
||||||
|
"y": 485.170148361568,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fab005",
|
||||||
|
"width": 392.02349853515625,
|
||||||
|
"height": 388.1683520208971,
|
||||||
|
"seed": 1622389102,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 299,
|
||||||
|
"versionNonce": 385652471,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "zi6i3xeoTlw2jmvkvo0MH",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 756.6563720703125,
|
||||||
|
"y": 807.8286743164062,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"width": 148,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1862147767,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Goroutine Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ellipse",
|
||||||
|
"version": 410,
|
||||||
|
"versionNonce": 1442166777,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "YREBQWDaV41cof7PNs-br",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 630.8078652393413,
|
||||||
|
"y": 573.218292236328,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"width": 218.25456981428613,
|
||||||
|
"height": 216.10826137312208,
|
||||||
|
"seed": 2138441529,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 241,
|
||||||
|
"versionNonce": 843993305,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "GLANOsn9G3AgWIiZsTm0k",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 686.0673217773438,
|
||||||
|
"y": 733.8128662109375,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"width": 105,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1548483929,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Block Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ellipse",
|
||||||
|
"version": 547,
|
||||||
|
"versionNonce": 488539447,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "4JSZd_8EU30-i5ZTcEMII",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 669.7872068781337,
|
||||||
|
"y": 574.3515319824218,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fa5252",
|
||||||
|
"width": 143.066548976275,
|
||||||
|
"height": 141.65963712110846,
|
||||||
|
"seed": 714197463,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 337,
|
||||||
|
"versionNonce": 347726382,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "9INmL5p1bzQ4ybvAY_FvP",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 684.9630126953125,
|
||||||
|
"y": 635.8465576171875,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"width": 114,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 2132545303,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Mutex Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ellipse",
|
||||||
|
"version": 700,
|
||||||
|
"versionNonce": 933676631,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "WowgALfO30J7LlVnLjWSY",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 864.6472817432475,
|
||||||
|
"y": 577.3910805262379,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 140.0686567283485,
|
||||||
|
"height": 138.69122604941987,
|
||||||
|
"seed": 460035961,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 197,
|
||||||
|
"versionNonce": 1715728558,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "Y_QmsQGgj_OEe1xJWA90D",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 889.7316589355468,
|
||||||
|
"y": 637.8959048747429,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"width": 94,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 513434745,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "CPU Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "center",
|
||||||
|
"verticalAlign": "middle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "arrow",
|
||||||
|
"version": 685,
|
||||||
|
"versionNonce": 556082670,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "LQL7eklipWPJw7N6IV0k3",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 1046.9965418640527,
|
||||||
|
"y": 765.9002716163905,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 144.2815760437402,
|
||||||
|
"height": 6.835452280452955,
|
||||||
|
"seed": 1019757362,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": {
|
||||||
|
"focus": 0.09220703124999999,
|
||||||
|
"gap": 9.483194464072312,
|
||||||
|
"elementId": "r5QpngwDotW31qiS-84QZ"
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-144.2815760437402,
|
||||||
|
-6.835452280452955
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 234,
|
||||||
|
"versionNonce": 663195186,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "r5QpngwDotW31qiS-84QZ",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 1056.479736328125,
|
||||||
|
"y": 738.490736219618,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 239,
|
||||||
|
"height": 75,
|
||||||
|
"seed": 529830642,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [
|
||||||
|
"LQL7eklipWPJw7N6IV0k3"
|
||||||
|
],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Untracked Waiting Time\ne.g. I/O, Syscalls, Sleep,\nScheduler Backlog, etc.",
|
||||||
|
"baseline": 68,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "arrow",
|
||||||
|
"version": 188,
|
||||||
|
"versionNonce": 87819511,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "BH5c8zmvtzjHySRm1GZOB",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 177.8948669433594,
|
||||||
|
"y": 389.87994384765625,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 334.8977329984625,
|
||||||
|
"height": 0.303227850731389,
|
||||||
|
"seed": 905268695,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": null,
|
||||||
|
"endBinding": {
|
||||||
|
"elementId": "DT1c4m8VCacvhSdiUcK3K",
|
||||||
|
"focus": -0.047098311036471635,
|
||||||
|
"gap": 14.24469253864686
|
||||||
|
},
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
334.8977329984625,
|
||||||
|
-0.303227850731389
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 151,
|
||||||
|
"versionNonce": 2894329,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "DT1c4m8VCacvhSdiUcK3K",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 527.0372924804688,
|
||||||
|
"y": 376.4291076660156,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 97,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 2055025303,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [
|
||||||
|
"BH5c8zmvtzjHySRm1GZOB"
|
||||||
|
],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Real Time",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 323,
|
||||||
|
"versionNonce": 804748857,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "SNbwAWQEwwTH7J5l7yExz",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 178.53466796875,
|
||||||
|
"y": 336.39166259765625,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"width": 165.1668701171875,
|
||||||
|
"height": 35.5604248046875,
|
||||||
|
"seed": 410318135,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 122,
|
||||||
|
"versionNonce": 961994489,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "1sxMCW-plp7_uNKHrZJ13",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 220.16162109375,
|
||||||
|
"y": 343.5514831542969,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fab005",
|
||||||
|
"width": 97,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1588541015,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "doStuff1()",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"version": 29,
|
||||||
|
"versionNonce": 390918135,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "BdsEqyfj0izYHykOviXP-",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 178.1519775390625,
|
||||||
|
"y": 380.7745056152344,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fab005",
|
||||||
|
"width": 0,
|
||||||
|
"height": 21.947662353515625,
|
||||||
|
"seed": 266744121,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": null,
|
||||||
|
"endBinding": null,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": null,
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
21.947662353515625
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "line",
|
||||||
|
"version": 237,
|
||||||
|
"versionNonce": 70479609,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "Ngp0cS95KlyTzApzR7ZV2",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 345.88088042160564,
|
||||||
|
"y": 380.3093566894531,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fab005",
|
||||||
|
"width": 0,
|
||||||
|
"height": 21.947662353515625,
|
||||||
|
"seed": 1368225719,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": null,
|
||||||
|
"endBinding": null,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": null,
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
21.947662353515625
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 40,
|
||||||
|
"versionNonce": 507107607,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "R4usAXLmRgnzUTbtTE9NM",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 165.52973496819067,
|
||||||
|
"y": 408.647611177885,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fab005",
|
||||||
|
"width": 25,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 631824569,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "0s",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 202,
|
||||||
|
"versionNonce": 1572677593,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "dckeEuAPShssVtkjy2C8I",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 338.96007912228555,
|
||||||
|
"y": 410.28450461471147,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fab005",
|
||||||
|
"width": 16,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 2000766935,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "1s",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 346,
|
||||||
|
"versionNonce": 964755481,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "ok9rk5WDp8xn1Qi-tSrrr",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 498.30740704523805,
|
||||||
|
"y": 407.80578483763713,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fab005",
|
||||||
|
"width": 25,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1298572215,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "2s",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "rectangle",
|
||||||
|
"version": 446,
|
||||||
|
"versionNonce": 200367575,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "eexikhxknvYvYmmcOo-ul",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 346.45037841796875,
|
||||||
|
"y": 336.39166259765625,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"width": 165.1668701171875,
|
||||||
|
"height": 35.5604248046875,
|
||||||
|
"seed": 1342601751,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 259,
|
||||||
|
"versionNonce": 894383513,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "OxEmug0EizIQ-QxmKEAI4",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 388.07733154296875,
|
||||||
|
"y": 343.5514831542969,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#fab005",
|
||||||
|
"width": 106,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 373527255,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "doStuff2()",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5nPCmBZUtW-sy9jSYVrnr",
|
||||||
|
"type": "arrow",
|
||||||
|
"x": 565.5727717042007,
|
||||||
|
"y": 723.9286336591438,
|
||||||
|
"width": 96.63453504774316,
|
||||||
|
"height": 0.0035721776366699487,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"seed": 2009323314,
|
||||||
|
"version": 139,
|
||||||
|
"versionNonce": 156517294,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElementIds": null,
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
96.63453504774316,
|
||||||
|
0.0035721776366699487
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "qGeURJQ0SK2OA3yANfDzs",
|
||||||
|
"focus": -0.1943830635497902,
|
||||||
|
"gap": 4.673326280381815
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Zw3pCq23-wlOAG9qzCGEn",
|
||||||
|
"type": "arrow",
|
||||||
|
"x": 566.5300145644317,
|
||||||
|
"y": 615.9900400381694,
|
||||||
|
"width": 147.2325357856023,
|
||||||
|
"height": 0,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"seed": 1500343342,
|
||||||
|
"version": 378,
|
||||||
|
"versionNonce": 1898901614,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElementIds": null,
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
147.2325357856023,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "xX3KMMOFeoWOYKAxIHlez",
|
||||||
|
"focus": -0.08419197923811227,
|
||||||
|
"gap": 9.557968665994167
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"version": 258,
|
||||||
|
"versionNonce": 1735386670,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "xX3KMMOFeoWOYKAxIHlez",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 442.97204589843744,
|
||||||
|
"y": 604.5424397786458,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 114,
|
||||||
|
"height": 25,
|
||||||
|
"seed": 1832387353,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"boundElementIds": [
|
||||||
|
"kBCBSYv6myf_GunPogGXE",
|
||||||
|
"Zw3pCq23-wlOAG9qzCGEn"
|
||||||
|
],
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"text": "Mutex Wait",
|
||||||
|
"baseline": 18,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "qGeURJQ0SK2OA3yANfDzs",
|
||||||
|
"type": "text",
|
||||||
|
"x": 342.8994454238188,
|
||||||
|
"y": 713.8550031458082,
|
||||||
|
"width": 218,
|
||||||
|
"height": 25,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"seed": 1013246894,
|
||||||
|
"version": 133,
|
||||||
|
"versionNonce": 171504754,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElementIds": [
|
||||||
|
"5nPCmBZUtW-sy9jSYVrnr"
|
||||||
|
],
|
||||||
|
"text": "Mutex + Channel Wait",
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top",
|
||||||
|
"baseline": 18
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "arrow",
|
||||||
|
"version": 1468,
|
||||||
|
"versionNonce": 308051182,
|
||||||
|
"isDeleted": false,
|
||||||
|
"id": "kBCBSYv6myf_GunPogGXE",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"angle": 0,
|
||||||
|
"x": 1049.8156880887022,
|
||||||
|
"y": 621.7754266468776,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#82c91e",
|
||||||
|
"width": 73.68763800422926,
|
||||||
|
"height": 0,
|
||||||
|
"seed": 1548243191,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "round",
|
||||||
|
"boundElementIds": [],
|
||||||
|
"startBinding": {
|
||||||
|
"elementId": "o7HqqenoMX9Jbq_HhYpVp",
|
||||||
|
"focus": -0.11262693564110121,
|
||||||
|
"gap": 14.676232378519217
|
||||||
|
},
|
||||||
|
"endBinding": null,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"startArrowhead": null,
|
||||||
|
"endArrowhead": "arrow",
|
||||||
|
"points": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-73.68763800422926,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "o7HqqenoMX9Jbq_HhYpVp",
|
||||||
|
"type": "text",
|
||||||
|
"x": 1064.4919204672215,
|
||||||
|
"y": 607.8675899513638,
|
||||||
|
"width": 210,
|
||||||
|
"height": 25,
|
||||||
|
"angle": 0,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "#228be6",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"strokeStyle": "solid",
|
||||||
|
"roughness": 1,
|
||||||
|
"opacity": 100,
|
||||||
|
"groupIds": [],
|
||||||
|
"strokeSharpness": "sharp",
|
||||||
|
"seed": 2043685486,
|
||||||
|
"version": 372,
|
||||||
|
"versionNonce": 290735922,
|
||||||
|
"isDeleted": false,
|
||||||
|
"boundElementIds": [
|
||||||
|
"kBCBSYv6myf_GunPogGXE"
|
||||||
|
],
|
||||||
|
"text": "User and Kernel Time",
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": 1,
|
||||||
|
"textAlign": "left",
|
||||||
|
"verticalAlign": "top",
|
||||||
|
"baseline": 18
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"appState": {
|
||||||
|
"gridSize": null,
|
||||||
|
"viewBackgroundColor": "#ffffff"
|
||||||
|
}
|
||||||
|
}
|
BIN
scheduler.png
Normal file
After Width: | Height: | Size: 318 KiB |