= golang == tooling staticcheck (popular as of 2025):: https://staticcheck.dev/ == execution traces https://go.dev/blog/execution-traces-2024 == race conditions, CPU profiling and memory profiling go test -cover -race -shuffle=on -vet=all -failfast ## based on https://github.com/bradfitz/talk-yapc-asia-2015/blob/master/talk.md 1. Write tests to catch data races. Run $ go test -v 2. Run with race detector. $ go test -v -race 3. To fix data race problems use functional style, mutex or atomic 4. Write benchmarks to do some CPU profiling: $ go test -v -run=^$ -bench=. 5. Collect data about the CPU: $ go test -v -run=^$ -bench=. -benchtime=2s -cpuprofile=prof.cpu 6. Run pprof to read created demo.test $ go tool pprof demo.test prof.cpu > top > top --cum > list handleHi > web # requires installation of graphviz 7. Memory profiling with --alloc_space $ go tool pprof --alloc_space demo.test prof.mem > top > top --cum > list BenchmarkHi > list handleHi == golang GC via FOSDEM 2025: “Go-ing Easy on Memory: Writing GC-Friendly code” phases: 1. initial mark (mark root objects) 2. concurrent mark (follow pointers and mark) 3. concurrent sweep (remove items) improvements: reduce:: • reduce the size of objects • design APIs so they accept slices as arguments not as return value to avoid escaping • closure variables might escape to heap • interface{} and generics are always on the heap • avoid pointers (string, time.Time, maps with reference types, …) • use a struct of two u32 as key, not its string representation reuse:: • sync.Pool is a thread-safe memory allocation pool (reuses same bytes) - use it for big objects or often-used objects (e.g. request object in HTTP handler) • thread-safe in the sense that the calls Get() and Put() are thread-safe, not your data • Get() and Put() should return a pointer! • don't forget to call Put() to return • reuses memory, does not allocate memory • reuse slice through "a := []int{1, 2, 3, 4,5}; a := append(a[:0], 10, 20, 30)" recycle:: GOGC=100 … if the memory usage doubled (= +100%) then trigger the GC GOMEMLIMIT= GODEBUG=gctrace=1 ./run-go-program dumps GC stats analysis with line-by-line profiling: go tool pprof -alloc_objects -list=BenchmarkOne mem.out escape analysis: go build -gcflags="-m=1|2|3" main.go via FOSDEM 2018 "Make your Go go faster!" go test -cpuprofile=cpu.out go tool pprof cpu.out via GopherCon 2025 "Advancing Go Garbage Collection with Green Tea" (Go 1.26) • go GC is a tracing garbage collector (with mark-sweep algorithm) • marking is done concurrently, parallelized • sweeping is incremental • 20% of CPU time is spent with garbage collection (significant majority spent on marking) • previously: • marking happens with LIFO (i.e. stack) ⇒ DFS • now: • GC tracks now pages in work list and not objects • GC now tracks seen bit & scanned bit per object • FIFO (i.e. queue) for work list (= pages)