• Péter Szilágyi's avatar
    Godeps, vendor: convert dependency management to trash (#3198) · 289b3071
    Péter Szilágyi authored
    This commit converts the dependency management from Godeps to the vendor
    folder, also switching the tool from godep to trash. Since the upstream tool
    lacks a few features proposed via a few PRs, until those PRs are merged in
    (if), use github.com/karalabe/trash.
    
    You can update dependencies via trash --update.
    
    All dependencies have been updated to their latest version.
    
    Parts of the build system are reworked to drop old notions of Godeps and
    invocation of the go vet command so that it doesn't run against the vendor
    folder, as that will just blow up during vetting.
    
    The conversion drops OpenCL (and hence GPU mining support) from ethash and our
    codebase. The short reasoning is that there's noone to maintain and having
    opencl libs in our deps messes up builds as go install ./... tries to build
    them, failing with unsatisfied link errors for the C OpenCL deps.
    
    golang.org/x/net/context is not vendored in. We expect it to be fetched by the
    user (i.e. using go get). To keep ci.go builds reproducible the package is
    "vendored" in build/_vendor.
    289b3071
runtime.go 8.63 KB
package metrics

import (
	"runtime"
	"runtime/pprof"
	"time"
)

var (
	memStats       runtime.MemStats
	runtimeMetrics struct {
		MemStats struct {
			Alloc         Gauge
			BuckHashSys   Gauge
			DebugGC       Gauge
			EnableGC      Gauge
			Frees         Gauge
			HeapAlloc     Gauge
			HeapIdle      Gauge
			HeapInuse     Gauge
			HeapObjects   Gauge
			HeapReleased  Gauge
			HeapSys       Gauge
			LastGC        Gauge
			Lookups       Gauge
			Mallocs       Gauge
			MCacheInuse   Gauge
			MCacheSys     Gauge
			MSpanInuse    Gauge
			MSpanSys      Gauge
			NextGC        Gauge
			NumGC         Gauge
			GCCPUFraction GaugeFloat64
			PauseNs       Histogram
			PauseTotalNs  Gauge
			StackInuse    Gauge
			StackSys      Gauge
			Sys           Gauge
			TotalAlloc    Gauge
		}
		NumCgoCall   Gauge
		NumGoroutine Gauge
		NumThread    Gauge
		ReadMemStats Timer
	}
	frees       uint64
	lookups     uint64
	mallocs     uint64
	numGC       uint32
	numCgoCalls int64

	threadCreateProfile = pprof.Lookup("threadcreate")
)

// Capture new values for the Go runtime statistics exported in
// runtime.MemStats.  This is designed to be called as a goroutine.
func CaptureRuntimeMemStats(r Registry, d time.Duration) {
	for _ = range time.Tick(d) {
		CaptureRuntimeMemStatsOnce(r)
	}
}

// Capture new values for the Go runtime statistics exported in
// runtime.MemStats.  This is designed to be called in a background
// goroutine.  Giving a registry which has not been given to
// RegisterRuntimeMemStats will panic.
//
// Be very careful with this because runtime.ReadMemStats calls the C
// functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld()
// and that last one does what it says on the tin.
func CaptureRuntimeMemStatsOnce(r Registry) {
	t := time.Now()
	runtime.ReadMemStats(&memStats) // This takes 50-200us.
	runtimeMetrics.ReadMemStats.UpdateSince(t)

	runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc))
	runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys))
	if memStats.DebugGC {
		runtimeMetrics.MemStats.DebugGC.Update(1)
	} else {
		runtimeMetrics.MemStats.DebugGC.Update(0)
	}
	if memStats.EnableGC {
		runtimeMetrics.MemStats.EnableGC.Update(1)
	} else {
		runtimeMetrics.MemStats.EnableGC.Update(0)
	}

	runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees))
	runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc))
	runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle))
	runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse))
	runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects))
	runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased))
	runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys))
	runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC))
	runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups))
	runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs))
	runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse))
	runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys))
	runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse))
	runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys))
	runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC))
	runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC))
	runtimeMetrics.MemStats.GCCPUFraction.Update(gcCPUFraction(&memStats))

	// <https://code.google.com/p/go/source/browse/src/pkg/runtime/mgc0.c>
	i := numGC % uint32(len(memStats.PauseNs))
	ii := memStats.NumGC % uint32(len(memStats.PauseNs))
	if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) {
		for i = 0; i < uint32(len(memStats.PauseNs)); i++ {
			runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
		}
	} else {
		if i > ii {
			for ; i < uint32(len(memStats.PauseNs)); i++ {
				runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
			}
			i = 0
		}
		for ; i < ii; i++ {
			runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
		}
	}
	frees = memStats.Frees
	lookups = memStats.Lookups
	mallocs = memStats.Mallocs
	numGC = memStats.NumGC

	runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs))
	runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse))
	runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys))
	runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys))
	runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc))

	currentNumCgoCalls := numCgoCall()
	runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls)
	numCgoCalls = currentNumCgoCalls

	runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine()))

	runtimeMetrics.NumThread.Update(int64(threadCreateProfile.Count()))
}

// Register runtimeMetrics for the Go runtime statistics exported in runtime and
// specifically runtime.MemStats.  The runtimeMetrics are named by their
// fully-qualified Go symbols, i.e. runtime.MemStats.Alloc.
func RegisterRuntimeMemStats(r Registry) {
	runtimeMetrics.MemStats.Alloc = NewGauge()
	runtimeMetrics.MemStats.BuckHashSys = NewGauge()
	runtimeMetrics.MemStats.DebugGC = NewGauge()
	runtimeMetrics.MemStats.EnableGC = NewGauge()
	runtimeMetrics.MemStats.Frees = NewGauge()
	runtimeMetrics.MemStats.HeapAlloc = NewGauge()
	runtimeMetrics.MemStats.HeapIdle = NewGauge()
	runtimeMetrics.MemStats.HeapInuse = NewGauge()
	runtimeMetrics.MemStats.HeapObjects = NewGauge()
	runtimeMetrics.MemStats.HeapReleased = NewGauge()
	runtimeMetrics.MemStats.HeapSys = NewGauge()
	runtimeMetrics.MemStats.LastGC = NewGauge()
	runtimeMetrics.MemStats.Lookups = NewGauge()
	runtimeMetrics.MemStats.Mallocs = NewGauge()
	runtimeMetrics.MemStats.MCacheInuse = NewGauge()
	runtimeMetrics.MemStats.MCacheSys = NewGauge()
	runtimeMetrics.MemStats.MSpanInuse = NewGauge()
	runtimeMetrics.MemStats.MSpanSys = NewGauge()
	runtimeMetrics.MemStats.NextGC = NewGauge()
	runtimeMetrics.MemStats.NumGC = NewGauge()
	runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64()
	runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015))
	runtimeMetrics.MemStats.PauseTotalNs = NewGauge()
	runtimeMetrics.MemStats.StackInuse = NewGauge()
	runtimeMetrics.MemStats.StackSys = NewGauge()
	runtimeMetrics.MemStats.Sys = NewGauge()
	runtimeMetrics.MemStats.TotalAlloc = NewGauge()
	runtimeMetrics.NumCgoCall = NewGauge()
	runtimeMetrics.NumGoroutine = NewGauge()
	runtimeMetrics.NumThread = NewGauge()
	runtimeMetrics.ReadMemStats = NewTimer()

	r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc)
	r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys)
	r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC)
	r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC)
	r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees)
	r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc)
	r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle)
	r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse)
	r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects)
	r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased)
	r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys)
	r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC)
	r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups)
	r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs)
	r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse)
	r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys)
	r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse)
	r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys)
	r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC)
	r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC)
	r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction)
	r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs)
	r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs)
	r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse)
	r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys)
	r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys)
	r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc)
	r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall)
	r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine)
	r.Register("runtime.NumThread", runtimeMetrics.NumThread)
	r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats)
}