@@ -5,50 +5,80 @@ package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggreg
55
66import (
77 "context"
8+ "math"
89 "sync"
10+ "sync/atomic"
911 "time"
1012
1113 "go.opentelemetry.io/otel/attribute"
1214 "go.opentelemetry.io/otel/sdk/metric/metricdata"
1315)
1416
1517type sumValue [N int64 | float64 ] struct {
16- n N
17- res FilteredExemplarReservoir [N ]
18- attrs attribute.Set
18+ nFloatBits uint64
19+ nInt uint64
20+ res FilteredExemplarReservoir [N ]
21+ attrs attribute.Set
22+ }
23+
24+ func (s * sumValue [N ]) val () N {
25+ fval := math .Float64frombits (atomic .LoadUint64 (& s .nFloatBits ))
26+ ival := atomic .LoadUint64 (& s .nInt )
27+ return N (fval + float64 (ival ))
1928}
2029
2130// valueMap is the storage for sums.
2231type valueMap [N int64 | float64 ] struct {
23- sync.Mutex
32+ sync.RWMutex
2433 newRes func (attribute.Set ) FilteredExemplarReservoir [N ]
2534 limit limiter [sumValue [N ]]
26- values map [attribute.Distinct ]sumValue [N ]
35+ values map [attribute.Distinct ]* sumValue [N ]
2736}
2837
2938func newValueMap [N int64 | float64 ](limit int , r func (attribute.Set ) FilteredExemplarReservoir [N ]) * valueMap [N ] {
3039 return & valueMap [N ]{
3140 newRes : r ,
3241 limit : newLimiter [sumValue [N ]](limit ),
33- values : make (map [attribute.Distinct ]sumValue [N ]),
42+ values : make (map [attribute.Distinct ]* sumValue [N ]),
3443 }
3544}
3645
37- func (s * valueMap [N ]) measure (ctx context.Context , value N , fltrAttr attribute.Set , droppedAttr []attribute.KeyValue ) {
38- s .Lock ()
39- defer s .Unlock ()
40-
46+ func (s * valueMap [N ]) getOrCreateSumValue (fltrAttr attribute.Set , droppedAttr []attribute.KeyValue ) * sumValue [N ] {
47+ s .RLock ()
4148 attr := s .limit .Attributes (fltrAttr , s .values )
4249 v , ok := s .values [attr .Equivalent ()]
50+ s .RUnlock ()
4351 if ! ok {
44- v .res = s .newRes (attr )
52+ v = & sumValue [N ]{
53+ res : s .newRes (attr ),
54+ attrs : attr ,
55+ }
56+ s .Lock ()
57+ s .values [attr .Equivalent ()] = v
58+ s .Unlock ()
4559 }
60+ return v
61+ }
4662
47- v . attrs = attr
48- v . n += value
63+ func ( s * valueMap [ N ]) measure ( ctx context. Context , value N , fltrAttr attribute. Set , droppedAttr []attribute. KeyValue ) {
64+ v := s . getOrCreateSumValue ( fltrAttr , droppedAttr )
4965 v .res .Offer (ctx , value , droppedAttr )
5066
51- s .values [attr .Equivalent ()] = v
67+ ival := uint64 (value )
68+ // This case is where the value is an int, or if it is a whole-numbered float.
69+ if float64 (ival ) == float64 (value ) {
70+ atomic .AddUint64 (& v .nInt , ival )
71+ return
72+ }
73+
74+ // Value must be a float below.
75+ for {
76+ oldBits := atomic .LoadUint64 (& v .nFloatBits )
77+ newBits := math .Float64bits (math .Float64frombits (oldBits ) + float64 (value ))
78+ if atomic .CompareAndSwapUint64 (& v .nFloatBits , oldBits , newBits ) {
79+ return
80+ }
81+ }
5282}
5383
5484// newSum returns an aggregator that summarizes a set of measurements as their
@@ -92,7 +122,7 @@ func (s *sum[N]) delta(
92122 dPts [i ].Attributes = val .attrs
93123 dPts [i ].StartTime = s .start
94124 dPts [i ].Time = t
95- dPts [i ].Value = val .n
125+ dPts [i ].Value = val .val ()
96126 collectExemplars (& dPts [i ].Exemplars , val .res .Collect )
97127 i ++
98128 }
@@ -129,7 +159,7 @@ func (s *sum[N]) cumulative(
129159 dPts [i ].Attributes = value .attrs
130160 dPts [i ].StartTime = s .start
131161 dPts [i ].Time = t
132- dPts [i ].Value = value .n
162+ dPts [i ].Value = value .val ()
133163 collectExemplars (& dPts [i ].Exemplars , value .res .Collect )
134164 // TODO (#3006): This will use an unbounded amount of memory if there
135165 // are unbounded number of attribute sets being aggregated. Attribute
@@ -189,15 +219,15 @@ func (s *precomputedSum[N]) delta(
189219
190220 var i int
191221 for key , value := range s .values {
192- delta := value .n - s .reported [key ]
222+ delta := value .val () - s .reported [key ]
193223
194224 dPts [i ].Attributes = value .attrs
195225 dPts [i ].StartTime = s .start
196226 dPts [i ].Time = t
197227 dPts [i ].Value = delta
198228 collectExemplars (& dPts [i ].Exemplars , value .res .Collect )
199229
200- newReported [key ] = value .n
230+ newReported [key ] = value .val ()
201231 i ++
202232 }
203233 // Unused attribute sets do not report.
@@ -234,7 +264,7 @@ func (s *precomputedSum[N]) cumulative(
234264 dPts [i ].Attributes = val .attrs
235265 dPts [i ].StartTime = s .start
236266 dPts [i ].Time = t
237- dPts [i ].Value = val .n
267+ dPts [i ].Value = val .val ()
238268 collectExemplars (& dPts [i ].Exemplars , val .res .Collect )
239269
240270 i ++
0 commit comments