gitlab.com/aquachain/aquachain@v1.17.16-rc3.0.20221018032414-e3ddf1e1c055/common/metrics/runtime.go (about)

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