github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/util/gctuner/README.md (about) 1 # gctuner 2 3 ## Introduction 4 5 Inspired 6 by [How We Saved 70K Cores Across 30 Mission-Critical Services (Large-Scale, Semi-Automated Go GC Tuning @Uber)](https://eng.uber.com/how-we-saved-70k-cores-across-30-mission-critical-services/) 7 . 8 9 ```text 10 _______________ => limit: host/cgroup memory hard limit 11 | | 12 |---------------| => gc_trigger: heap_live + heap_live * GCPercent / 100 13 | | 14 |---------------| 15 | heap_live | 16 |_______________| 17 ``` 18 19 Go runtime trigger GC when hit `gc_trigger` which affected by `GCPercent` and `heap_live`. 20 21 Assuming that we have stable traffic, our application will always have 100 MB live heap, so the runtime will trigger GC 22 once heap hits 200 MB(by default GOGC=100). The heap size will be changed like: `100MB => 200MB => 100MB => 200MB => ...`. 23 24 But in real production, our application may have 4 GB memory resources, so no need to GC so frequently. 25 26 The gctuner helps to change the GOGC(GCPercent) dynamically at runtime, set the appropriate GCPercent according to current 27 memory usage. 28 29 ### How it works 30 31 ```text 32 _______________ => limit: host/cgroup memory hard limit 33 | | 34 |---------------| => threshold: increase GCPercent when gc_trigger < threshold 35 | | 36 |---------------| => gc_trigger: heap_live + heap_live * GCPercent / 100 37 | | 38 |---------------| 39 | heap_live | 40 |_______________| 41 42 threshold = inuse + inuse * (gcPercent / 100) 43 => gcPercent = (threshold - inuse) / inuse * 100 44 45 if threshold < 2*inuse, so gcPercent < 100, and GC positively to avoid OOM 46 if threshold > 2*inuse, so gcPercent > 100, and GC negatively to reduce GC times 47 ``` 48 49 ## Usage 50 51 The recommended threshold is 70% of the memory limit. 52 53 ```go 54 55 // Get mem limit from the host machine or cgroup file. 56 limit := 4 * 1024 * 1024 * 1024 57 threshold := limit * 0.7 58 59 gctuner.Tuning(threshold) 60 ```