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  }