Source file
src/runtime/metrics.go
1
2
3
4
5 package runtime
6
7
8
9 import (
10 "internal/godebugs"
11 "internal/runtime/atomic"
12 "internal/runtime/gc"
13 "unsafe"
14 )
15
16 var (
17
18
19
20
21
22
23 metricsSema uint32 = 1
24 metricsInit bool
25 metrics map[string]metricData
26
27 sizeClassBuckets []float64
28 timeHistBuckets []float64
29 )
30
31 type metricData struct {
32
33
34
35 deps statDepSet
36
37
38
39 compute func(in *statAggregate, out *metricValue)
40 }
41
42 func metricsLock() {
43
44
45
46 semacquire1(&metricsSema, true, 0, 0, waitReasonSemacquire)
47 if raceenabled {
48 raceacquire(unsafe.Pointer(&metricsSema))
49 }
50 }
51
52 func metricsUnlock() {
53 if raceenabled {
54 racerelease(unsafe.Pointer(&metricsSema))
55 }
56 semrelease(&metricsSema)
57 }
58
59
60
61
62 func initMetrics() {
63 if metricsInit {
64 return
65 }
66
67 sizeClassBuckets = make([]float64, gc.NumSizeClasses, gc.NumSizeClasses+1)
68
69
70
71 sizeClassBuckets[0] = 1
72 for i := 1; i < gc.NumSizeClasses; i++ {
73
74
75
76
77
78
79
80
81
82
83
84 sizeClassBuckets[i] = float64(gc.SizeClassToSize[i] + 1)
85 }
86 sizeClassBuckets = append(sizeClassBuckets, float64Inf())
87
88 timeHistBuckets = timeHistogramMetricsBuckets()
89 metrics = map[string]metricData{
90 "/cgo/go-to-c-calls:calls": {
91 compute: func(_ *statAggregate, out *metricValue) {
92 out.kind = metricKindUint64
93 out.scalar = uint64(NumCgoCall())
94 },
95 },
96 "/cpu/classes/gc/mark/assist:cpu-seconds": {
97 deps: makeStatDepSet(cpuStatsDep),
98 compute: func(in *statAggregate, out *metricValue) {
99 out.kind = metricKindFloat64
100 out.scalar = float64bits(nsToSec(in.cpuStats.GCAssistTime))
101 },
102 },
103 "/cpu/classes/gc/mark/dedicated:cpu-seconds": {
104 deps: makeStatDepSet(cpuStatsDep),
105 compute: func(in *statAggregate, out *metricValue) {
106 out.kind = metricKindFloat64
107 out.scalar = float64bits(nsToSec(in.cpuStats.GCDedicatedTime))
108 },
109 },
110 "/cpu/classes/gc/mark/idle:cpu-seconds": {
111 deps: makeStatDepSet(cpuStatsDep),
112 compute: func(in *statAggregate, out *metricValue) {
113 out.kind = metricKindFloat64
114 out.scalar = float64bits(nsToSec(in.cpuStats.GCIdleTime))
115 },
116 },
117 "/cpu/classes/gc/pause:cpu-seconds": {
118 deps: makeStatDepSet(cpuStatsDep),
119 compute: func(in *statAggregate, out *metricValue) {
120 out.kind = metricKindFloat64
121 out.scalar = float64bits(nsToSec(in.cpuStats.GCPauseTime))
122 },
123 },
124 "/cpu/classes/gc/total:cpu-seconds": {
125 deps: makeStatDepSet(cpuStatsDep),
126 compute: func(in *statAggregate, out *metricValue) {
127 out.kind = metricKindFloat64
128 out.scalar = float64bits(nsToSec(in.cpuStats.GCTotalTime))
129 },
130 },
131 "/cpu/classes/idle:cpu-seconds": {
132 deps: makeStatDepSet(cpuStatsDep),
133 compute: func(in *statAggregate, out *metricValue) {
134 out.kind = metricKindFloat64
135 out.scalar = float64bits(nsToSec(in.cpuStats.IdleTime))
136 },
137 },
138 "/cpu/classes/scavenge/assist:cpu-seconds": {
139 deps: makeStatDepSet(cpuStatsDep),
140 compute: func(in *statAggregate, out *metricValue) {
141 out.kind = metricKindFloat64
142 out.scalar = float64bits(nsToSec(in.cpuStats.ScavengeAssistTime))
143 },
144 },
145 "/cpu/classes/scavenge/background:cpu-seconds": {
146 deps: makeStatDepSet(cpuStatsDep),
147 compute: func(in *statAggregate, out *metricValue) {
148 out.kind = metricKindFloat64
149 out.scalar = float64bits(nsToSec(in.cpuStats.ScavengeBgTime))
150 },
151 },
152 "/cpu/classes/scavenge/total:cpu-seconds": {
153 deps: makeStatDepSet(cpuStatsDep),
154 compute: func(in *statAggregate, out *metricValue) {
155 out.kind = metricKindFloat64
156 out.scalar = float64bits(nsToSec(in.cpuStats.ScavengeTotalTime))
157 },
158 },
159 "/cpu/classes/total:cpu-seconds": {
160 deps: makeStatDepSet(cpuStatsDep),
161 compute: func(in *statAggregate, out *metricValue) {
162 out.kind = metricKindFloat64
163 out.scalar = float64bits(nsToSec(in.cpuStats.TotalTime))
164 },
165 },
166 "/cpu/classes/user:cpu-seconds": {
167 deps: makeStatDepSet(cpuStatsDep),
168 compute: func(in *statAggregate, out *metricValue) {
169 out.kind = metricKindFloat64
170 out.scalar = float64bits(nsToSec(in.cpuStats.UserTime))
171 },
172 },
173 "/gc/cleanups/executed:cleanups": {
174 deps: makeStatDepSet(finalStatsDep),
175 compute: func(in *statAggregate, out *metricValue) {
176 out.kind = metricKindUint64
177 out.scalar = in.finalStats.cleanupsExecuted
178 },
179 },
180 "/gc/cleanups/queued:cleanups": {
181 deps: makeStatDepSet(finalStatsDep),
182 compute: func(in *statAggregate, out *metricValue) {
183 out.kind = metricKindUint64
184 out.scalar = in.finalStats.cleanupsQueued
185 },
186 },
187 "/gc/cycles/automatic:gc-cycles": {
188 deps: makeStatDepSet(sysStatsDep),
189 compute: func(in *statAggregate, out *metricValue) {
190 out.kind = metricKindUint64
191 out.scalar = in.sysStats.gcCyclesDone - in.sysStats.gcCyclesForced
192 },
193 },
194 "/gc/cycles/forced:gc-cycles": {
195 deps: makeStatDepSet(sysStatsDep),
196 compute: func(in *statAggregate, out *metricValue) {
197 out.kind = metricKindUint64
198 out.scalar = in.sysStats.gcCyclesForced
199 },
200 },
201 "/gc/cycles/total:gc-cycles": {
202 deps: makeStatDepSet(sysStatsDep),
203 compute: func(in *statAggregate, out *metricValue) {
204 out.kind = metricKindUint64
205 out.scalar = in.sysStats.gcCyclesDone
206 },
207 },
208 "/gc/finalizers/executed:finalizers": {
209 deps: makeStatDepSet(finalStatsDep),
210 compute: func(in *statAggregate, out *metricValue) {
211 out.kind = metricKindUint64
212 out.scalar = in.finalStats.finalizersExecuted
213 },
214 },
215 "/gc/finalizers/queued:finalizers": {
216 deps: makeStatDepSet(finalStatsDep),
217 compute: func(in *statAggregate, out *metricValue) {
218 out.kind = metricKindUint64
219 out.scalar = in.finalStats.finalizersQueued
220 },
221 },
222 "/gc/scan/globals:bytes": {
223 deps: makeStatDepSet(gcStatsDep),
224 compute: func(in *statAggregate, out *metricValue) {
225 out.kind = metricKindUint64
226 out.scalar = in.gcStats.globalsScan
227 },
228 },
229 "/gc/scan/heap:bytes": {
230 deps: makeStatDepSet(gcStatsDep),
231 compute: func(in *statAggregate, out *metricValue) {
232 out.kind = metricKindUint64
233 out.scalar = in.gcStats.heapScan
234 },
235 },
236 "/gc/scan/stack:bytes": {
237 deps: makeStatDepSet(gcStatsDep),
238 compute: func(in *statAggregate, out *metricValue) {
239 out.kind = metricKindUint64
240 out.scalar = in.gcStats.stackScan
241 },
242 },
243 "/gc/scan/total:bytes": {
244 deps: makeStatDepSet(gcStatsDep),
245 compute: func(in *statAggregate, out *metricValue) {
246 out.kind = metricKindUint64
247 out.scalar = in.gcStats.totalScan
248 },
249 },
250 "/gc/heap/allocs-by-size:bytes": {
251 deps: makeStatDepSet(heapStatsDep),
252 compute: func(in *statAggregate, out *metricValue) {
253 hist := out.float64HistOrInit(sizeClassBuckets)
254 hist.counts[len(hist.counts)-1] = in.heapStats.largeAllocCount
255
256
257 for i, count := range in.heapStats.smallAllocCount[1:] {
258 hist.counts[i] = count
259 }
260 },
261 },
262 "/gc/heap/allocs:bytes": {
263 deps: makeStatDepSet(heapStatsDep),
264 compute: func(in *statAggregate, out *metricValue) {
265 out.kind = metricKindUint64
266 out.scalar = in.heapStats.totalAllocated
267 },
268 },
269 "/gc/heap/allocs:objects": {
270 deps: makeStatDepSet(heapStatsDep),
271 compute: func(in *statAggregate, out *metricValue) {
272 out.kind = metricKindUint64
273 out.scalar = in.heapStats.totalAllocs
274 },
275 },
276 "/gc/heap/frees-by-size:bytes": {
277 deps: makeStatDepSet(heapStatsDep),
278 compute: func(in *statAggregate, out *metricValue) {
279 hist := out.float64HistOrInit(sizeClassBuckets)
280 hist.counts[len(hist.counts)-1] = in.heapStats.largeFreeCount
281
282
283 for i, count := range in.heapStats.smallFreeCount[1:] {
284 hist.counts[i] = count
285 }
286 },
287 },
288 "/gc/heap/frees:bytes": {
289 deps: makeStatDepSet(heapStatsDep),
290 compute: func(in *statAggregate, out *metricValue) {
291 out.kind = metricKindUint64
292 out.scalar = in.heapStats.totalFreed
293 },
294 },
295 "/gc/heap/frees:objects": {
296 deps: makeStatDepSet(heapStatsDep),
297 compute: func(in *statAggregate, out *metricValue) {
298 out.kind = metricKindUint64
299 out.scalar = in.heapStats.totalFrees
300 },
301 },
302 "/gc/heap/goal:bytes": {
303 deps: makeStatDepSet(sysStatsDep),
304 compute: func(in *statAggregate, out *metricValue) {
305 out.kind = metricKindUint64
306 out.scalar = in.sysStats.heapGoal
307 },
308 },
309 "/gc/gomemlimit:bytes": {
310 compute: func(in *statAggregate, out *metricValue) {
311 out.kind = metricKindUint64
312 out.scalar = uint64(gcController.memoryLimit.Load())
313 },
314 },
315 "/gc/gogc:percent": {
316 compute: func(in *statAggregate, out *metricValue) {
317 out.kind = metricKindUint64
318 out.scalar = uint64(gcController.gcPercent.Load())
319 },
320 },
321 "/gc/heap/live:bytes": {
322 deps: makeStatDepSet(heapStatsDep),
323 compute: func(in *statAggregate, out *metricValue) {
324 out.kind = metricKindUint64
325 out.scalar = gcController.heapMarked
326 },
327 },
328 "/gc/heap/objects:objects": {
329 deps: makeStatDepSet(heapStatsDep),
330 compute: func(in *statAggregate, out *metricValue) {
331 out.kind = metricKindUint64
332 out.scalar = in.heapStats.numObjects
333 },
334 },
335 "/gc/heap/tiny/allocs:objects": {
336 deps: makeStatDepSet(heapStatsDep),
337 compute: func(in *statAggregate, out *metricValue) {
338 out.kind = metricKindUint64
339 out.scalar = in.heapStats.tinyAllocCount
340 },
341 },
342 "/gc/limiter/last-enabled:gc-cycle": {
343 compute: func(_ *statAggregate, out *metricValue) {
344 out.kind = metricKindUint64
345 out.scalar = uint64(gcCPULimiter.lastEnabledCycle.Load())
346 },
347 },
348 "/gc/pauses:seconds": {
349 compute: func(_ *statAggregate, out *metricValue) {
350
351 sched.stwTotalTimeGC.write(out)
352 },
353 },
354 "/gc/stack/starting-size:bytes": {
355 compute: func(in *statAggregate, out *metricValue) {
356 out.kind = metricKindUint64
357 out.scalar = uint64(startingStackSize)
358 },
359 },
360 "/memory/classes/heap/free:bytes": {
361 deps: makeStatDepSet(heapStatsDep),
362 compute: func(in *statAggregate, out *metricValue) {
363 out.kind = metricKindUint64
364 out.scalar = uint64(in.heapStats.committed - in.heapStats.inHeap -
365 in.heapStats.inStacks - in.heapStats.inWorkBufs)
366 },
367 },
368 "/memory/classes/heap/objects:bytes": {
369 deps: makeStatDepSet(heapStatsDep),
370 compute: func(in *statAggregate, out *metricValue) {
371 out.kind = metricKindUint64
372 out.scalar = in.heapStats.inObjects
373 },
374 },
375 "/memory/classes/heap/released:bytes": {
376 deps: makeStatDepSet(heapStatsDep),
377 compute: func(in *statAggregate, out *metricValue) {
378 out.kind = metricKindUint64
379 out.scalar = uint64(in.heapStats.released)
380 },
381 },
382 "/memory/classes/heap/stacks:bytes": {
383 deps: makeStatDepSet(heapStatsDep),
384 compute: func(in *statAggregate, out *metricValue) {
385 out.kind = metricKindUint64
386 out.scalar = uint64(in.heapStats.inStacks)
387 },
388 },
389 "/memory/classes/heap/unused:bytes": {
390 deps: makeStatDepSet(heapStatsDep),
391 compute: func(in *statAggregate, out *metricValue) {
392 out.kind = metricKindUint64
393 out.scalar = uint64(in.heapStats.inHeap) - in.heapStats.inObjects
394 },
395 },
396 "/memory/classes/metadata/mcache/free:bytes": {
397 deps: makeStatDepSet(sysStatsDep),
398 compute: func(in *statAggregate, out *metricValue) {
399 out.kind = metricKindUint64
400 out.scalar = in.sysStats.mCacheSys - in.sysStats.mCacheInUse
401 },
402 },
403 "/memory/classes/metadata/mcache/inuse:bytes": {
404 deps: makeStatDepSet(sysStatsDep),
405 compute: func(in *statAggregate, out *metricValue) {
406 out.kind = metricKindUint64
407 out.scalar = in.sysStats.mCacheInUse
408 },
409 },
410 "/memory/classes/metadata/mspan/free:bytes": {
411 deps: makeStatDepSet(sysStatsDep),
412 compute: func(in *statAggregate, out *metricValue) {
413 out.kind = metricKindUint64
414 out.scalar = in.sysStats.mSpanSys - in.sysStats.mSpanInUse
415 },
416 },
417 "/memory/classes/metadata/mspan/inuse:bytes": {
418 deps: makeStatDepSet(sysStatsDep),
419 compute: func(in *statAggregate, out *metricValue) {
420 out.kind = metricKindUint64
421 out.scalar = in.sysStats.mSpanInUse
422 },
423 },
424 "/memory/classes/metadata/other:bytes": {
425 deps: makeStatDepSet(heapStatsDep, sysStatsDep),
426 compute: func(in *statAggregate, out *metricValue) {
427 out.kind = metricKindUint64
428 out.scalar = uint64(in.heapStats.inWorkBufs) + in.sysStats.gcMiscSys
429 },
430 },
431 "/memory/classes/os-stacks:bytes": {
432 deps: makeStatDepSet(sysStatsDep),
433 compute: func(in *statAggregate, out *metricValue) {
434 out.kind = metricKindUint64
435 out.scalar = in.sysStats.stacksSys
436 },
437 },
438 "/memory/classes/other:bytes": {
439 deps: makeStatDepSet(sysStatsDep),
440 compute: func(in *statAggregate, out *metricValue) {
441 out.kind = metricKindUint64
442 out.scalar = in.sysStats.otherSys
443 },
444 },
445 "/memory/classes/profiling/buckets:bytes": {
446 deps: makeStatDepSet(sysStatsDep),
447 compute: func(in *statAggregate, out *metricValue) {
448 out.kind = metricKindUint64
449 out.scalar = in.sysStats.buckHashSys
450 },
451 },
452 "/memory/classes/total:bytes": {
453 deps: makeStatDepSet(heapStatsDep, sysStatsDep),
454 compute: func(in *statAggregate, out *metricValue) {
455 out.kind = metricKindUint64
456 out.scalar = uint64(in.heapStats.committed+in.heapStats.released) +
457 in.sysStats.stacksSys + in.sysStats.mSpanSys +
458 in.sysStats.mCacheSys + in.sysStats.buckHashSys +
459 in.sysStats.gcMiscSys + in.sysStats.otherSys
460 },
461 },
462 "/sched/gomaxprocs:threads": {
463 compute: func(_ *statAggregate, out *metricValue) {
464 out.kind = metricKindUint64
465 out.scalar = uint64(gomaxprocs)
466 },
467 },
468 "/sched/goroutines:goroutines": {
469 deps: makeStatDepSet(schedStatsDep),
470 compute: func(in *statAggregate, out *metricValue) {
471 out.kind = metricKindUint64
472 out.scalar = in.schedStats.gTotal
473 },
474 },
475 "/sched/goroutines/not-in-go:goroutines": {
476 deps: makeStatDepSet(schedStatsDep),
477 compute: func(in *statAggregate, out *metricValue) {
478 out.kind = metricKindUint64
479 out.scalar = in.schedStats.gNonGo
480 },
481 },
482 "/sched/goroutines/running:goroutines": {
483 deps: makeStatDepSet(schedStatsDep),
484 compute: func(in *statAggregate, out *metricValue) {
485 out.kind = metricKindUint64
486 out.scalar = in.schedStats.gRunning
487 },
488 },
489 "/sched/goroutines/runnable:goroutines": {
490 deps: makeStatDepSet(schedStatsDep),
491 compute: func(in *statAggregate, out *metricValue) {
492 out.kind = metricKindUint64
493 out.scalar = in.schedStats.gRunnable
494 },
495 },
496 "/sched/goroutines/waiting:goroutines": {
497 deps: makeStatDepSet(schedStatsDep),
498 compute: func(in *statAggregate, out *metricValue) {
499 out.kind = metricKindUint64
500 out.scalar = in.schedStats.gWaiting
501 },
502 },
503 "/sched/goroutines-created:goroutines": {
504 deps: makeStatDepSet(schedStatsDep),
505 compute: func(in *statAggregate, out *metricValue) {
506 out.kind = metricKindUint64
507 out.scalar = in.schedStats.gCreated
508 },
509 },
510 "/sched/latencies:seconds": {
511 compute: func(_ *statAggregate, out *metricValue) {
512 sched.timeToRun.write(out)
513 },
514 },
515 "/sched/pauses/stopping/gc:seconds": {
516 compute: func(_ *statAggregate, out *metricValue) {
517 sched.stwStoppingTimeGC.write(out)
518 },
519 },
520 "/sched/pauses/stopping/other:seconds": {
521 compute: func(_ *statAggregate, out *metricValue) {
522 sched.stwStoppingTimeOther.write(out)
523 },
524 },
525 "/sched/pauses/total/gc:seconds": {
526 compute: func(_ *statAggregate, out *metricValue) {
527 sched.stwTotalTimeGC.write(out)
528 },
529 },
530 "/sched/pauses/total/other:seconds": {
531 compute: func(_ *statAggregate, out *metricValue) {
532 sched.stwTotalTimeOther.write(out)
533 },
534 },
535 "/sched/threads/total:threads": {
536 deps: makeStatDepSet(schedStatsDep),
537 compute: func(in *statAggregate, out *metricValue) {
538 out.kind = metricKindUint64
539 out.scalar = in.schedStats.threads
540 },
541 },
542 "/sync/mutex/wait/total:seconds": {
543 compute: func(_ *statAggregate, out *metricValue) {
544 out.kind = metricKindFloat64
545 out.scalar = float64bits(nsToSec(totalMutexWaitTimeNanos()))
546 },
547 },
548 }
549
550 for _, info := range godebugs.All {
551 if !info.Opaque {
552 metrics["/godebug/non-default-behavior/"+info.Name+":events"] = metricData{compute: compute0}
553 }
554 }
555
556 metricsInit = true
557 }
558
559 func compute0(_ *statAggregate, out *metricValue) {
560 out.kind = metricKindUint64
561 out.scalar = 0
562 }
563
564 type metricReader func() uint64
565
566 func (f metricReader) compute(_ *statAggregate, out *metricValue) {
567 out.kind = metricKindUint64
568 out.scalar = f()
569 }
570
571
572 func godebug_registerMetric(name string, read func() uint64) {
573 metricsLock()
574 initMetrics()
575 d, ok := metrics[name]
576 if !ok {
577 throw("runtime: unexpected metric registration for " + name)
578 }
579 d.compute = metricReader(read).compute
580 metrics[name] = d
581 metricsUnlock()
582 }
583
584
585
586 type statDep uint
587
588 const (
589 heapStatsDep statDep = iota
590 sysStatsDep
591 cpuStatsDep
592 gcStatsDep
593 finalStatsDep
594 schedStatsDep
595 numStatsDeps
596 )
597
598
599
600
601 type statDepSet [1]uint64
602
603
604 func makeStatDepSet(deps ...statDep) statDepSet {
605 var s statDepSet
606 for _, d := range deps {
607 s[d/64] |= 1 << (d % 64)
608 }
609 return s
610 }
611
612
613 func (s statDepSet) difference(b statDepSet) statDepSet {
614 var c statDepSet
615 for i := range s {
616 c[i] = s[i] &^ b[i]
617 }
618 return c
619 }
620
621
622 func (s statDepSet) union(b statDepSet) statDepSet {
623 var c statDepSet
624 for i := range s {
625 c[i] = s[i] | b[i]
626 }
627 return c
628 }
629
630
631 func (s *statDepSet) empty() bool {
632 for _, c := range s {
633 if c != 0 {
634 return false
635 }
636 }
637 return true
638 }
639
640
641 func (s *statDepSet) has(d statDep) bool {
642 return s[d/64]&(1<<(d%64)) != 0
643 }
644
645
646
647
648
649
650 type heapStatsAggregate struct {
651 heapStatsDelta
652
653
654
655
656 inObjects uint64
657
658
659 numObjects uint64
660
661
662
663 totalAllocated uint64
664
665
666
667 totalFreed uint64
668
669
670
671 totalAllocs uint64
672
673
674
675 totalFrees uint64
676 }
677
678
679 func (a *heapStatsAggregate) compute() {
680 memstats.heapStats.read(&a.heapStatsDelta)
681
682
683 a.totalAllocs = a.largeAllocCount
684 a.totalFrees = a.largeFreeCount
685 a.totalAllocated = a.largeAlloc
686 a.totalFreed = a.largeFree
687 for i := range a.smallAllocCount {
688 na := a.smallAllocCount[i]
689 nf := a.smallFreeCount[i]
690 a.totalAllocs += na
691 a.totalFrees += nf
692 a.totalAllocated += na * uint64(gc.SizeClassToSize[i])
693 a.totalFreed += nf * uint64(gc.SizeClassToSize[i])
694 }
695 a.inObjects = a.totalAllocated - a.totalFreed
696 a.numObjects = a.totalAllocs - a.totalFrees
697 }
698
699
700
701
702
703
704
705
706 type sysStatsAggregate struct {
707 stacksSys uint64
708 mSpanSys uint64
709 mSpanInUse uint64
710 mCacheSys uint64
711 mCacheInUse uint64
712 buckHashSys uint64
713 gcMiscSys uint64
714 otherSys uint64
715 heapGoal uint64
716 gcCyclesDone uint64
717 gcCyclesForced uint64
718 }
719
720
721 func (a *sysStatsAggregate) compute() {
722 a.stacksSys = memstats.stacks_sys.load()
723 a.buckHashSys = memstats.buckhash_sys.load()
724 a.gcMiscSys = memstats.gcMiscSys.load()
725 a.otherSys = memstats.other_sys.load()
726 a.heapGoal = gcController.heapGoal()
727 a.gcCyclesDone = uint64(memstats.numgc)
728 a.gcCyclesForced = uint64(memstats.numforcedgc)
729
730 systemstack(func() {
731 lock(&mheap_.lock)
732 a.mSpanSys = memstats.mspan_sys.load()
733 a.mSpanInUse = uint64(mheap_.spanalloc.inuse)
734 a.mCacheSys = memstats.mcache_sys.load()
735 a.mCacheInUse = uint64(mheap_.cachealloc.inuse)
736 unlock(&mheap_.lock)
737 })
738 }
739
740
741
742 type cpuStatsAggregate struct {
743 cpuStats
744 }
745
746
747 func (a *cpuStatsAggregate) compute() {
748 a.cpuStats = work.cpuStats
749
750
751
752
753
754 }
755
756
757
758 type gcStatsAggregate struct {
759 heapScan uint64
760 stackScan uint64
761 globalsScan uint64
762 totalScan uint64
763 }
764
765
766 func (a *gcStatsAggregate) compute() {
767 a.heapScan = gcController.heapScan.Load()
768 a.stackScan = gcController.lastStackScan.Load()
769 a.globalsScan = gcController.globalsScan.Load()
770 a.totalScan = a.heapScan + a.stackScan + a.globalsScan
771 }
772
773
774
775 type finalStatsAggregate struct {
776 finalizersQueued uint64
777 finalizersExecuted uint64
778 cleanupsQueued uint64
779 cleanupsExecuted uint64
780 }
781
782
783 func (a *finalStatsAggregate) compute() {
784 a.finalizersQueued, a.finalizersExecuted = finReadQueueStats()
785 a.cleanupsQueued, a.cleanupsExecuted = gcCleanups.readQueueStats()
786 }
787
788
789
790 type schedStatsAggregate struct {
791 gTotal uint64
792 gRunning uint64
793 gRunnable uint64
794 gNonGo uint64
795 gWaiting uint64
796 gCreated uint64
797 threads uint64
798 }
799
800
801 func (a *schedStatsAggregate) compute() {
802
803
804
805
806 lock(&sched.lock)
807
808
809
810 a.threads = uint64(mcount()) - uint64(extraMInUse.Load()) - uint64(extraMLength.Load())
811
812
813 a.gCreated += sched.goroutinesCreated.Load()
814 for _, p := range allp {
815 if p == nil || p.status == _Pdead {
816 break
817 }
818 a.gCreated += p.goroutinesCreated
819 switch p.status {
820 case _Prunning:
821 if thread, ok := setBlockOnExitSyscall(p); ok {
822 thread.resume()
823 a.gNonGo++
824 } else {
825 a.gRunning++
826 }
827 case _Pgcstop:
828
829
830
831
832 }
833
834 for {
835 h := atomic.Load(&p.runqhead)
836 t := atomic.Load(&p.runqtail)
837 next := atomic.Loaduintptr((*uintptr)(&p.runnext))
838 runnable := int32(t - h)
839 if atomic.Load(&p.runqhead) != h || runnable < 0 {
840 continue
841 }
842 if next != 0 {
843 runnable++
844 }
845 a.gRunnable += uint64(runnable)
846 break
847 }
848 }
849
850
851 a.gRunnable += uint64(sched.runq.size)
852
853
854 nGsyscallNoP := sched.nGsyscallNoP.Load()
855
856
857 if nGsyscallNoP >= 0 {
858 a.gNonGo += uint64(nGsyscallNoP)
859 }
860
861
862
863
864 a.gTotal = uint64(gcount(true))
865 if a.gTotal < a.gRunning+a.gRunnable+a.gNonGo {
866 a.gWaiting = 0
867 } else {
868 a.gWaiting = a.gTotal - (a.gRunning + a.gRunnable + a.gNonGo)
869 }
870
871 unlock(&sched.lock)
872 }
873
874
875
876 func nsToSec(ns int64) float64 {
877 return float64(ns) / 1e9
878 }
879
880
881
882
883
884
885 type statAggregate struct {
886 ensured statDepSet
887 heapStats heapStatsAggregate
888 sysStats sysStatsAggregate
889 cpuStats cpuStatsAggregate
890 gcStats gcStatsAggregate
891 finalStats finalStatsAggregate
892 schedStats schedStatsAggregate
893 }
894
895
896
897 func (a *statAggregate) ensure(deps *statDepSet) {
898 missing := deps.difference(a.ensured)
899 if missing.empty() {
900 return
901 }
902 for i := statDep(0); i < numStatsDeps; i++ {
903 if !missing.has(i) {
904 continue
905 }
906 switch i {
907 case heapStatsDep:
908 a.heapStats.compute()
909 case sysStatsDep:
910 a.sysStats.compute()
911 case cpuStatsDep:
912 a.cpuStats.compute()
913 case gcStatsDep:
914 a.gcStats.compute()
915 case finalStatsDep:
916 a.finalStats.compute()
917 case schedStatsDep:
918 a.schedStats.compute()
919 }
920 }
921 a.ensured = a.ensured.union(missing)
922 }
923
924
925
926 type metricKind int
927
928 const (
929
930
931 metricKindBad metricKind = iota
932 metricKindUint64
933 metricKindFloat64
934 metricKindFloat64Histogram
935 )
936
937
938
939 type metricSample struct {
940 name string
941 value metricValue
942 }
943
944
945
946 type metricValue struct {
947 kind metricKind
948 scalar uint64
949 pointer unsafe.Pointer
950 }
951
952
953
954
955 func (v *metricValue) float64HistOrInit(buckets []float64) *metricFloat64Histogram {
956 var hist *metricFloat64Histogram
957 if v.kind == metricKindFloat64Histogram && v.pointer != nil {
958 hist = (*metricFloat64Histogram)(v.pointer)
959 } else {
960 v.kind = metricKindFloat64Histogram
961 hist = new(metricFloat64Histogram)
962 v.pointer = unsafe.Pointer(hist)
963 }
964 hist.buckets = buckets
965 if len(hist.counts) != len(hist.buckets)-1 {
966 hist.counts = make([]uint64, len(buckets)-1)
967 }
968 return hist
969 }
970
971
972
973 type metricFloat64Histogram struct {
974 counts []uint64
975 buckets []float64
976 }
977
978
979
980
981
982
983 var agg statAggregate
984
985 type metricName struct {
986 name string
987 kind metricKind
988 }
989
990
991
992
993
994 func readMetricNames() []string {
995 metricsLock()
996 initMetrics()
997 n := len(metrics)
998 metricsUnlock()
999
1000 list := make([]string, 0, n)
1001
1002 metricsLock()
1003 for name := range metrics {
1004 list = append(list, name)
1005 }
1006 metricsUnlock()
1007
1008 return list
1009 }
1010
1011
1012
1013
1014 func readMetrics(samplesp unsafe.Pointer, len int, cap int) {
1015 metricsLock()
1016
1017
1018 initMetrics()
1019
1020
1021 readMetricsLocked(samplesp, len, cap)
1022 metricsUnlock()
1023 }
1024
1025
1026
1027
1028
1029 func readMetricsLocked(samplesp unsafe.Pointer, len int, cap int) {
1030
1031 sl := slice{samplesp, len, cap}
1032 samples := *(*[]metricSample)(unsafe.Pointer(&sl))
1033
1034
1035 agg = statAggregate{}
1036
1037
1038 for i := range samples {
1039 sample := &samples[i]
1040 data, ok := metrics[sample.name]
1041 if !ok {
1042 sample.value.kind = metricKindBad
1043 continue
1044 }
1045
1046
1047 agg.ensure(&data.deps)
1048
1049
1050 data.compute(&agg, &sample.value)
1051 }
1052 }
1053
View as plain text