github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/gc_controller.go (about) 1 package instrumentation 2 3 import ( 4 "context" 5 "runtime/debug" 6 "time" 7 8 "github.com/Rookout/GoSDK/pkg/logger" 9 ) 10 11 type gcController struct { 12 gcEnabled bool 13 triggerCounter int 14 enableGCTimer <-chan time.Time 15 originalGCPercent int 16 } 17 18 func newGCController() *gcController { 19 originalGCPercent := debug.SetGCPercent(-1) 20 debug.SetGCPercent(originalGCPercent) 21 22 return &gcController{ 23 gcEnabled: true, 24 triggerCounter: 0, 25 enableGCTimer: nil, 26 originalGCPercent: originalGCPercent, 27 } 28 } 29 30 func (g *gcController) start(ctx context.Context, triggerChan chan bool) { 31 for { 32 select { 33 case <-ctx.Done(): 34 g.enableGC() 35 return 36 case triggerStart := <-triggerChan: 37 if triggerStart { 38 if g.triggerStart() { 39 g.disableGC() 40 } 41 } else { 42 if g.triggerEnd() { 43 g.startEnableGCTimer() 44 } 45 } 46 47 case <-g.enableGCTimer: 48 g.enableGC() 49 } 50 } 51 } 52 53 func (g *gcController) triggerStart() bool { 54 g.triggerCounter++ 55 56 return true 57 } 58 59 func (g *gcController) triggerEnd() bool { 60 g.triggerCounter-- 61 62 63 if g.triggerCounter < 0 { 64 logger.Logger().Fatalf("Something bad happened. Trigger counter is a negative number: %d\n", g.triggerCounter) 65 g.triggerCounter = 0 66 return true 67 } 68 69 70 return g.triggerCounter == 0 71 } 72 73 func (g *gcController) disableGC() { 74 prevGCPercent := debug.SetGCPercent(-1) 75 if prevGCPercent != -1 && prevGCPercent != g.originalGCPercent { 76 logger.Logger().Infof("GC percent was changed from %d to %d", g.originalGCPercent, prevGCPercent) 77 g.originalGCPercent = prevGCPercent 78 } 79 g.enableGCTimer = nil 80 } 81 82 func (g *gcController) enableGC() { 83 debug.SetGCPercent(g.originalGCPercent) 84 } 85 86 func (g *gcController) startEnableGCTimer() { 87 g.enableGCTimer = time.After(1 * time.Millisecond) 88 }