runtime.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package metrics
  2. import (
  3. "runtime"
  4. "runtime/pprof"
  5. "time"
  6. )
  7. var (
  8. memStats runtime.MemStats
  9. runtimeMetrics struct {
  10. MemStats struct {
  11. Alloc Gauge
  12. BuckHashSys Gauge
  13. DebugGC Gauge
  14. EnableGC Gauge
  15. Frees Gauge
  16. HeapAlloc Gauge
  17. HeapIdle Gauge
  18. HeapInuse Gauge
  19. HeapObjects Gauge
  20. HeapReleased Gauge
  21. HeapSys Gauge
  22. LastGC Gauge
  23. Lookups Gauge
  24. Mallocs Gauge
  25. MCacheInuse Gauge
  26. MCacheSys Gauge
  27. MSpanInuse Gauge
  28. MSpanSys Gauge
  29. NextGC Gauge
  30. NumGC Gauge
  31. GCCPUFraction GaugeFloat64
  32. PauseNs Histogram
  33. PauseTotalNs Gauge
  34. StackInuse Gauge
  35. StackSys Gauge
  36. Sys Gauge
  37. TotalAlloc Gauge
  38. }
  39. NumCgoCall Gauge
  40. NumGoroutine Gauge
  41. NumThread Gauge
  42. ReadMemStats Timer
  43. }
  44. frees uint64
  45. lookups uint64
  46. mallocs uint64
  47. numGC uint32
  48. numCgoCalls int64
  49. threadCreateProfile = pprof.Lookup("threadcreate")
  50. )
  51. // Capture new values for the Go runtime statistics exported in
  52. // runtime.MemStats. This is designed to be called as a goroutine.
  53. func CaptureRuntimeMemStats(r Registry, d time.Duration) {
  54. for _ = range time.Tick(d) {
  55. CaptureRuntimeMemStatsOnce(r)
  56. }
  57. }
  58. // Capture new values for the Go runtime statistics exported in
  59. // runtime.MemStats. This is designed to be called in a background
  60. // goroutine. Giving a registry which has not been given to
  61. // RegisterRuntimeMemStats will panic.
  62. //
  63. // Be very careful with this because runtime.ReadMemStats calls the C
  64. // functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld()
  65. // and that last one does what it says on the tin.
  66. func CaptureRuntimeMemStatsOnce(r Registry) {
  67. t := time.Now()
  68. runtime.ReadMemStats(&memStats) // This takes 50-200us.
  69. runtimeMetrics.ReadMemStats.UpdateSince(t)
  70. runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc))
  71. runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys))
  72. if memStats.DebugGC {
  73. runtimeMetrics.MemStats.DebugGC.Update(1)
  74. } else {
  75. runtimeMetrics.MemStats.DebugGC.Update(0)
  76. }
  77. if memStats.EnableGC {
  78. runtimeMetrics.MemStats.EnableGC.Update(1)
  79. } else {
  80. runtimeMetrics.MemStats.EnableGC.Update(0)
  81. }
  82. runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees))
  83. runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc))
  84. runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle))
  85. runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse))
  86. runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects))
  87. runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased))
  88. runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys))
  89. runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC))
  90. runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups))
  91. runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs))
  92. runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse))
  93. runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys))
  94. runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse))
  95. runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys))
  96. runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC))
  97. runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC))
  98. runtimeMetrics.MemStats.GCCPUFraction.Update(gcCPUFraction(&memStats))
  99. // <https://code.google.com/p/go/source/browse/src/pkg/runtime/mgc0.c>
  100. i := numGC % uint32(len(memStats.PauseNs))
  101. ii := memStats.NumGC % uint32(len(memStats.PauseNs))
  102. if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) {
  103. for i = 0; i < uint32(len(memStats.PauseNs)); i++ {
  104. runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
  105. }
  106. } else {
  107. if i > ii {
  108. for ; i < uint32(len(memStats.PauseNs)); i++ {
  109. runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
  110. }
  111. i = 0
  112. }
  113. for ; i < ii; i++ {
  114. runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
  115. }
  116. }
  117. frees = memStats.Frees
  118. lookups = memStats.Lookups
  119. mallocs = memStats.Mallocs
  120. numGC = memStats.NumGC
  121. runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs))
  122. runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse))
  123. runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys))
  124. runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys))
  125. runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc))
  126. currentNumCgoCalls := numCgoCall()
  127. runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls)
  128. numCgoCalls = currentNumCgoCalls
  129. runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine()))
  130. runtimeMetrics.NumThread.Update(int64(threadCreateProfile.Count()))
  131. }
  132. // Register runtimeMetrics for the Go runtime statistics exported in runtime and
  133. // specifically runtime.MemStats. The runtimeMetrics are named by their
  134. // fully-qualified Go symbols, i.e. runtime.MemStats.Alloc.
  135. func RegisterRuntimeMemStats(r Registry) {
  136. runtimeMetrics.MemStats.Alloc = NewGauge()
  137. runtimeMetrics.MemStats.BuckHashSys = NewGauge()
  138. runtimeMetrics.MemStats.DebugGC = NewGauge()
  139. runtimeMetrics.MemStats.EnableGC = NewGauge()
  140. runtimeMetrics.MemStats.Frees = NewGauge()
  141. runtimeMetrics.MemStats.HeapAlloc = NewGauge()
  142. runtimeMetrics.MemStats.HeapIdle = NewGauge()
  143. runtimeMetrics.MemStats.HeapInuse = NewGauge()
  144. runtimeMetrics.MemStats.HeapObjects = NewGauge()
  145. runtimeMetrics.MemStats.HeapReleased = NewGauge()
  146. runtimeMetrics.MemStats.HeapSys = NewGauge()
  147. runtimeMetrics.MemStats.LastGC = NewGauge()
  148. runtimeMetrics.MemStats.Lookups = NewGauge()
  149. runtimeMetrics.MemStats.Mallocs = NewGauge()
  150. runtimeMetrics.MemStats.MCacheInuse = NewGauge()
  151. runtimeMetrics.MemStats.MCacheSys = NewGauge()
  152. runtimeMetrics.MemStats.MSpanInuse = NewGauge()
  153. runtimeMetrics.MemStats.MSpanSys = NewGauge()
  154. runtimeMetrics.MemStats.NextGC = NewGauge()
  155. runtimeMetrics.MemStats.NumGC = NewGauge()
  156. runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64()
  157. runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015))
  158. runtimeMetrics.MemStats.PauseTotalNs = NewGauge()
  159. runtimeMetrics.MemStats.StackInuse = NewGauge()
  160. runtimeMetrics.MemStats.StackSys = NewGauge()
  161. runtimeMetrics.MemStats.Sys = NewGauge()
  162. runtimeMetrics.MemStats.TotalAlloc = NewGauge()
  163. runtimeMetrics.NumCgoCall = NewGauge()
  164. runtimeMetrics.NumGoroutine = NewGauge()
  165. runtimeMetrics.NumThread = NewGauge()
  166. runtimeMetrics.ReadMemStats = NewTimer()
  167. r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc)
  168. r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys)
  169. r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC)
  170. r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC)
  171. r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees)
  172. r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc)
  173. r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle)
  174. r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse)
  175. r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects)
  176. r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased)
  177. r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys)
  178. r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC)
  179. r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups)
  180. r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs)
  181. r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse)
  182. r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys)
  183. r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse)
  184. r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys)
  185. r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC)
  186. r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC)
  187. r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction)
  188. r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs)
  189. r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs)
  190. r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse)
  191. r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys)
  192. r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys)
  193. r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc)
  194. r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall)
  195. r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine)
  196. r.Register("runtime.NumThread", runtimeMetrics.NumThread)
  197. r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats)
  198. }