/
gctune.go
61 lines (55 loc) · 1.27 KB
/
gctune.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Package gctune allows for easier management of the Go GC behavior.
package gctune
import (
"fmt"
"runtime"
"runtime/debug"
"sync"
"time"
)
var (
tSize int64 = -1
mu sync.RWMutex
)
func init() {
go monitor()
}
// SetTargetSysSize changes the desired maximum system memory to be used by
// this process. It returns the previously set value, or -1 if inset.
// (This doesn't work yet.)
func SetTargetSysSize(t int64) int64 {
mu.Lock()
defer mu.Unlock()
was := tSize
tSize = t
return was
}
func monitor() {
c := time.Tick(1 * time.Second)
mem := new(runtime.MemStats)
origPct := debug.SetGCPercent(100)
debug.SetGCPercent(origPct)
for _ = range c {
runtime.ReadMemStats(mem)
mu.Lock()
defer mu.Unlock()
if tSize < 0 {
continue
}
// Occupancy fraction: 70%. Don't GC before hitting this.
softLimit := float64(tSize) * 0.7
pct := softLimit / float64(mem.Alloc) * 100
fmt.Printf("gctune: pct: %0.5f, target: %d, softLimit: %0.2f, Alloc: %d, Sys: %d\n", pct, tSize, softLimit, mem.Alloc, mem.Sys)
if pct < 50 {
// If this is too low, GC frequency increases too much.
pct = 50
}
debug.SetGCPercent(int(pct))
if mem.Sys > uint64(tSize*70/100) {
fmt.Println("freeing")
debug.FreeOSMemory()
}
}
}
// debug.FreeOSMemory
// debug.SetGCPercent