18
18
metricsSema uint32 = 1
19
19
metricsInit bool
20
20
metrics map [string ]metricData
21
+
22
+ sizeClassBuckets []float64
21
23
)
22
24
23
25
type metricData struct {
@@ -38,6 +40,10 @@ func initMetrics() {
38
40
if metricsInit {
39
41
return
40
42
}
43
+ sizeClassBuckets = make ([]float64 , _NumSizeClasses )
44
+ for i := range sizeClassBuckets {
45
+ sizeClassBuckets [i ] = float64 (class_to_size [i ])
46
+ }
41
47
metrics = map [string ]metricData {
42
48
"/gc/cycles/automatic:gc-cycles" : {
43
49
deps : makeStatDepSet (sysStatsDep ),
@@ -60,6 +66,26 @@ func initMetrics() {
60
66
out .scalar = in .sysStats .gcCyclesDone
61
67
},
62
68
},
69
+ "/gc/heap/allocs-by-size:objects" : {
70
+ deps : makeStatDepSet (heapStatsDep ),
71
+ compute : func (in * statAggregate , out * metricValue ) {
72
+ hist := out .float64HistOrInit (sizeClassBuckets )
73
+ hist .counts [len (hist .counts )- 1 ] = uint64 (in .heapStats .largeAllocCount )
74
+ for i := range hist .buckets {
75
+ hist .counts [i ] = uint64 (in .heapStats .smallAllocCount [i ])
76
+ }
77
+ },
78
+ },
79
+ "/gc/heap/frees-by-size:objects" : {
80
+ deps : makeStatDepSet (heapStatsDep ),
81
+ compute : func (in * statAggregate , out * metricValue ) {
82
+ hist := out .float64HistOrInit (sizeClassBuckets )
83
+ hist .counts [len (hist .counts )- 1 ] = uint64 (in .heapStats .largeFreeCount )
84
+ for i := range hist .buckets {
85
+ hist .counts [i ] = uint64 (in .heapStats .smallFreeCount [i ])
86
+ }
87
+ },
88
+ },
63
89
"/gc/heap/goal:bytes" : {
64
90
deps : makeStatDepSet (sysStatsDep ),
65
91
compute : func (in * statAggregate , out * metricValue ) {
@@ -370,6 +396,32 @@ type metricValue struct {
370
396
pointer unsafe.Pointer // contains non-scalar values.
371
397
}
372
398
399
+ // float64HistOrInit tries to pull out an existing float64Histogram
400
+ // from the value, but if none exists, then it allocates one with
401
+ // the given buckets.
402
+ func (v * metricValue ) float64HistOrInit (buckets []float64 ) * metricFloat64Histogram {
403
+ var hist * metricFloat64Histogram
404
+ if v .kind == metricKindFloat64Histogram && v .pointer != nil {
405
+ hist = (* metricFloat64Histogram )(v .pointer )
406
+ } else {
407
+ v .kind = metricKindFloat64Histogram
408
+ hist = new (metricFloat64Histogram )
409
+ v .pointer = unsafe .Pointer (hist )
410
+ }
411
+ hist .buckets = buckets
412
+ if len (hist .counts ) != len (hist .buckets )+ 1 {
413
+ hist .counts = make ([]uint64 , len (buckets )+ 1 )
414
+ }
415
+ return hist
416
+ }
417
+
418
+ // metricFloat64Histogram is a runtime copy of runtime/metrics.Float64Histogram
419
+ // and must be kept structurally identical to that type.
420
+ type metricFloat64Histogram struct {
421
+ counts []uint64
422
+ buckets []float64
423
+ }
424
+
373
425
// agg is used by readMetrics, and is protected by metricsSema.
374
426
//
375
427
// Managed as a global variable because its pointer will be
0 commit comments