github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/metrics/runtime.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package metrics 19 20 import ( 21 "runtime" 22 "runtime/pprof" 23 "time" 24 ) 25 26 var ( 27 memStats runtime.MemStats 28 runtimeMetrics struct { 29 MemStats struct { 30 Alloc Gauge 31 BuckHashSys Gauge 32 DebugGC Gauge 33 EnableGC Gauge 34 Frees Gauge 35 HeapAlloc Gauge 36 HeapIdle Gauge 37 HeapInuse Gauge 38 HeapObjects Gauge 39 HeapReleased Gauge 40 HeapSys Gauge 41 LastGC Gauge 42 Lookups Gauge 43 Mallocs Gauge 44 MCacheInuse Gauge 45 MCacheSys Gauge 46 MSpanInuse Gauge 47 MSpanSys Gauge 48 NextGC Gauge 49 NumGC Gauge 50 GCCPUFraction GaugeFloat64 51 PauseNs Histogram 52 PauseTotalNs Gauge 53 StackInuse Gauge 54 StackSys Gauge 55 Sys Gauge 56 TotalAlloc Gauge 57 } 58 NumCgoCall Gauge 59 NumGoroutine Gauge 60 NumThread Gauge 61 ReadMemStats Timer 62 } 63 frees uint64 64 lookups uint64 65 mallocs uint64 66 numGC uint32 67 numCgoCalls int64 68 69 threadCreateProfile = pprof.Lookup("threadcreate") 70 ) 71 72 // Capture new values for the Go runtime statistics exported in 73 // runtime.MemStats. This is designed to be called as a goroutine. 74 func CaptureRuntimeMemStats(r Registry, d time.Duration) { 75 for range time.Tick(d) { 76 CaptureRuntimeMemStatsOnce(r) 77 } 78 } 79 80 // Capture new values for the Go runtime statistics exported in 81 // runtime.MemStats. This is designed to be called in a background 82 // goroutine. Giving a registry which has not been given to 83 // RegisterRuntimeMemStats will panic. 84 // 85 // Be very careful with this because runtime.ReadMemStats calls the C 86 // functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld() 87 // and that last one does what it says on the tin. 88 func CaptureRuntimeMemStatsOnce(r Registry) { 89 t := time.Now() 90 runtime.ReadMemStats(&memStats) // This takes 50-200us. 91 runtimeMetrics.ReadMemStats.UpdateSince(t) 92 93 runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc)) 94 runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys)) 95 if memStats.DebugGC { 96 runtimeMetrics.MemStats.DebugGC.Update(1) 97 } else { 98 runtimeMetrics.MemStats.DebugGC.Update(0) 99 } 100 if memStats.EnableGC { 101 runtimeMetrics.MemStats.EnableGC.Update(1) 102 } else { 103 runtimeMetrics.MemStats.EnableGC.Update(0) 104 } 105 106 runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees)) 107 runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc)) 108 runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle)) 109 runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse)) 110 runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects)) 111 runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased)) 112 runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys)) 113 runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC)) 114 runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups)) 115 runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs)) 116 runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse)) 117 runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys)) 118 runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse)) 119 runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys)) 120 runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC)) 121 runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC)) 122 runtimeMetrics.MemStats.GCCPUFraction.Update(gcCPUFraction(&memStats)) 123 124 // <https://code.google.com/p/go/source/browse/src/pkg/runtime/mgc0.c> 125 i := numGC % uint32(len(memStats.PauseNs)) 126 ii := memStats.NumGC % uint32(len(memStats.PauseNs)) 127 if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) { 128 for i = 0; i < uint32(len(memStats.PauseNs)); i++ { 129 runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) 130 } 131 } else { 132 if i > ii { 133 for ; i < uint32(len(memStats.PauseNs)); i++ { 134 runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) 135 } 136 i = 0 137 } 138 for ; i < ii; i++ { 139 runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) 140 } 141 } 142 frees = memStats.Frees 143 lookups = memStats.Lookups 144 mallocs = memStats.Mallocs 145 numGC = memStats.NumGC 146 147 runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs)) 148 runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse)) 149 runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys)) 150 runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys)) 151 runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc)) 152 153 currentNumCgoCalls := numCgoCall() 154 runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls) 155 numCgoCalls = currentNumCgoCalls 156 157 runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine())) 158 159 runtimeMetrics.NumThread.Update(int64(threadCreateProfile.Count())) 160 } 161 162 // Register runtimeMetrics for the Go runtime statistics exported in runtime and 163 // specifically runtime.MemStats. The runtimeMetrics are named by their 164 // fully-qualified Go symbols, i.e. runtime.MemStats.Alloc. 165 func RegisterRuntimeMemStats(r Registry) { 166 runtimeMetrics.MemStats.Alloc = NewGauge() 167 runtimeMetrics.MemStats.BuckHashSys = NewGauge() 168 runtimeMetrics.MemStats.DebugGC = NewGauge() 169 runtimeMetrics.MemStats.EnableGC = NewGauge() 170 runtimeMetrics.MemStats.Frees = NewGauge() 171 runtimeMetrics.MemStats.HeapAlloc = NewGauge() 172 runtimeMetrics.MemStats.HeapIdle = NewGauge() 173 runtimeMetrics.MemStats.HeapInuse = NewGauge() 174 runtimeMetrics.MemStats.HeapObjects = NewGauge() 175 runtimeMetrics.MemStats.HeapReleased = NewGauge() 176 runtimeMetrics.MemStats.HeapSys = NewGauge() 177 runtimeMetrics.MemStats.LastGC = NewGauge() 178 runtimeMetrics.MemStats.Lookups = NewGauge() 179 runtimeMetrics.MemStats.Mallocs = NewGauge() 180 runtimeMetrics.MemStats.MCacheInuse = NewGauge() 181 runtimeMetrics.MemStats.MCacheSys = NewGauge() 182 runtimeMetrics.MemStats.MSpanInuse = NewGauge() 183 runtimeMetrics.MemStats.MSpanSys = NewGauge() 184 runtimeMetrics.MemStats.NextGC = NewGauge() 185 runtimeMetrics.MemStats.NumGC = NewGauge() 186 runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() 187 runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) 188 runtimeMetrics.MemStats.PauseTotalNs = NewGauge() 189 runtimeMetrics.MemStats.StackInuse = NewGauge() 190 runtimeMetrics.MemStats.StackSys = NewGauge() 191 runtimeMetrics.MemStats.Sys = NewGauge() 192 runtimeMetrics.MemStats.TotalAlloc = NewGauge() 193 runtimeMetrics.NumCgoCall = NewGauge() 194 runtimeMetrics.NumGoroutine = NewGauge() 195 runtimeMetrics.NumThread = NewGauge() 196 runtimeMetrics.ReadMemStats = NewTimer() 197 198 r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) 199 r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) 200 r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) 201 r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) 202 r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) 203 r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) 204 r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) 205 r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) 206 r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) 207 r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) 208 r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) 209 r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) 210 r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) 211 r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) 212 r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) 213 r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) 214 r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) 215 r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) 216 r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) 217 r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) 218 r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) 219 r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) 220 r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) 221 r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) 222 r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) 223 r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) 224 r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) 225 r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) 226 r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) 227 r.Register("runtime.NumThread", runtimeMetrics.NumThread) 228 r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) 229 }