package runtime
import (
)
var (
metricsSema uint32 = 1
metricsInit bool
metrics map[string]metricData
sizeClassBuckets []float64
timeHistBuckets []float64
)
type metricData struct {
deps statDepSet
compute func(in *statAggregate, out *metricValue)
}
func () {
if metricsInit {
return
}
sizeClassBuckets = make([]float64, _NumSizeClasses, _NumSizeClasses+1)
sizeClassBuckets[0] = 1
for := 1; < _NumSizeClasses; ++ {
sizeClassBuckets[] = float64(class_to_size[] + 1)
}
sizeClassBuckets = append(sizeClassBuckets, float64Inf())
timeHistBuckets = timeHistogramMetricsBuckets()
metrics = map[string]metricData{
"/gc/cycles/automatic:gc-cycles": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.gcCyclesDone - .sysStats.gcCyclesForced
},
},
"/gc/cycles/forced:gc-cycles": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.gcCyclesForced
},
},
"/gc/cycles/total:gc-cycles": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.gcCyclesDone
},
},
"/gc/heap/allocs-by-size:bytes": {
deps: makeStatDepSet(heapStatsDep),
compute: func( *statAggregate, *metricValue) {
:= .float64HistOrInit(sizeClassBuckets)
.counts[len(.counts)-1] = uint64(.heapStats.largeAllocCount)
for , := range .heapStats.smallAllocCount[1:] {
.counts[] = uint64()
}
},
},
"/gc/heap/frees-by-size:bytes": {
deps: makeStatDepSet(heapStatsDep),
compute: func( *statAggregate, *metricValue) {
:= .float64HistOrInit(sizeClassBuckets)
.counts[len(.counts)-1] = uint64(.heapStats.largeFreeCount)
for , := range .heapStats.smallFreeCount[1:] {
.counts[] = uint64()
}
},
},
"/gc/heap/goal:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.heapGoal
},
},
"/gc/heap/objects:objects": {
deps: makeStatDepSet(heapStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .heapStats.numObjects
},
},
"/gc/pauses:seconds": {
compute: func( *statAggregate, *metricValue) {
:= .float64HistOrInit(timeHistBuckets)
.counts[0] = atomic.Load64(&memstats.gcPauseDist.underflow)
for := range memstats.gcPauseDist.counts {
.counts[+1] = atomic.Load64(&memstats.gcPauseDist.counts[])
}
},
},
"/memory/classes/heap/free:bytes": {
deps: makeStatDepSet(heapStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = uint64(.heapStats.committed - .heapStats.inHeap -
.heapStats.inStacks - .heapStats.inWorkBufs -
.heapStats.inPtrScalarBits)
},
},
"/memory/classes/heap/objects:bytes": {
deps: makeStatDepSet(heapStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .heapStats.inObjects
},
},
"/memory/classes/heap/released:bytes": {
deps: makeStatDepSet(heapStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = uint64(.heapStats.released)
},
},
"/memory/classes/heap/stacks:bytes": {
deps: makeStatDepSet(heapStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = uint64(.heapStats.inStacks)
},
},
"/memory/classes/heap/unused:bytes": {
deps: makeStatDepSet(heapStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = uint64(.heapStats.inHeap) - .heapStats.inObjects
},
},
"/memory/classes/metadata/mcache/free:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.mCacheSys - .sysStats.mCacheInUse
},
},
"/memory/classes/metadata/mcache/inuse:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.mCacheInUse
},
},
"/memory/classes/metadata/mspan/free:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.mSpanSys - .sysStats.mSpanInUse
},
},
"/memory/classes/metadata/mspan/inuse:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.mSpanInUse
},
},
"/memory/classes/metadata/other:bytes": {
deps: makeStatDepSet(heapStatsDep, sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = uint64(.heapStats.inWorkBufs+.heapStats.inPtrScalarBits) + .sysStats.gcMiscSys
},
},
"/memory/classes/os-stacks:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.stacksSys
},
},
"/memory/classes/other:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.otherSys
},
},
"/memory/classes/profiling/buckets:bytes": {
deps: makeStatDepSet(sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = .sysStats.buckHashSys
},
},
"/memory/classes/total:bytes": {
deps: makeStatDepSet(heapStatsDep, sysStatsDep),
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = uint64(.heapStats.committed+.heapStats.released) +
.sysStats.stacksSys + .sysStats.mSpanSys +
.sysStats.mCacheSys + .sysStats.buckHashSys +
.sysStats.gcMiscSys + .sysStats.otherSys
},
},
"/sched/goroutines:goroutines": {
compute: func( *statAggregate, *metricValue) {
.kind = metricKindUint64
.scalar = uint64(gcount())
},
},
}
metricsInit = true
}
type statDep uint
const (
heapStatsDep statDep = iota
sysStatsDep
numStatsDeps
)
type statDepSet [1]uint64
func ( ...statDep) statDepSet {
var statDepSet
for , := range {
[/64] |= 1 << ( % 64)
}
return
}
func ( statDepSet) ( statDepSet) statDepSet {
var statDepSet
for := range {
[] = [] &^ []
}
return
}
func ( statDepSet) ( statDepSet) statDepSet {
var statDepSet
for := range {
[] = [] | []
}
return
}
func ( *statDepSet) () bool {
for , := range {
if != 0 {
return false
}
}
return true
}
func ( *statDepSet) ( statDep) bool {
return [/64]&(1<<(%64)) != 0
}
type heapStatsAggregate struct {
heapStatsDelta
inObjects uint64
numObjects uint64
}
func ( *heapStatsAggregate) () {
memstats.heapStats.read(&.heapStatsDelta)
.inObjects = uint64(.largeAlloc - .largeFree)
.numObjects = uint64(.largeAllocCount - .largeFreeCount)
for := range .smallAllocCount {
:= uint64(.smallAllocCount[] - .smallFreeCount[])
.inObjects += * uint64(class_to_size[])
.numObjects +=
}
}
type sysStatsAggregate struct {
stacksSys uint64
mSpanSys uint64
mSpanInUse uint64
mCacheSys uint64
mCacheInUse uint64
buckHashSys uint64
gcMiscSys uint64
otherSys uint64
heapGoal uint64
gcCyclesDone uint64
gcCyclesForced uint64
}
func ( *sysStatsAggregate) () {
.stacksSys = memstats.stacks_sys.load()
.buckHashSys = memstats.buckhash_sys.load()
.gcMiscSys = memstats.gcMiscSys.load()
.otherSys = memstats.other_sys.load()
.heapGoal = atomic.Load64(&memstats.next_gc)
.gcCyclesDone = uint64(memstats.numgc)
.gcCyclesForced = uint64(memstats.numforcedgc)
systemstack(func() {
lock(&mheap_.lock)
.mSpanSys = memstats.mspan_sys.load()
.mSpanInUse = uint64(mheap_.spanalloc.inuse)
.mCacheSys = memstats.mcache_sys.load()
.mCacheInUse = uint64(mheap_.cachealloc.inuse)
unlock(&mheap_.lock)
})
}
type statAggregate struct {
ensured statDepSet
heapStats heapStatsAggregate
sysStats sysStatsAggregate
}
func ( *statAggregate) ( *statDepSet) {
:= .difference(.ensured)
if .empty() {
return
}
for := statDep(0); < numStatsDeps; ++ {
if !.has() {
continue
}
switch {
case heapStatsDep:
.heapStats.compute()
case sysStatsDep:
.sysStats.compute()
}
}
.ensured = .ensured.union()
}
type metricKind int
const (
metricKindBad metricKind = iota
metricKindUint64
metricKindFloat64
metricKindFloat64Histogram
)
type metricSample struct {
name string
value metricValue
}
type metricValue struct {
kind metricKind
scalar uint64
pointer unsafe.Pointer
}
func ( *metricValue) ( []float64) *metricFloat64Histogram {
var *metricFloat64Histogram
if .kind == metricKindFloat64Histogram && .pointer != nil {
= (*metricFloat64Histogram)(.pointer)
} else {
.kind = metricKindFloat64Histogram
= new(metricFloat64Histogram)
.pointer = unsafe.Pointer()
}
.buckets =
if len(.counts) != len(.buckets)-1 {
.counts = make([]uint64, len()-1)
}
return
}
type metricFloat64Histogram struct {
counts []uint64
buckets []float64
}
var agg statAggregate
func ( unsafe.Pointer, int, int) {
:= slice{, , }
:= *(*[]metricSample)(unsafe.Pointer(&))
semacquire1(&metricsSema, true, 0, 0)
initMetrics()
agg = statAggregate{}
for := range {
:= &[]
, := metrics[.name]
if ! {
.value.kind = metricKindBad
continue
}
agg.ensure(&.deps)
.compute(&agg, &.value)
}
semrelease(&metricsSema)
}