@@ -5,50 +5,81 @@ 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+ value atomic.Value // Contains N
21+ res FilteredExemplarReservoir [N ]
22+ attrs attribute.Set
23+ }
24+
25+ func (s * sumValue [N ]) val () N {
26+ fval := math .Float64frombits (atomic .LoadUint64 (& s .nFloatBits ))
27+ ival := atomic .LoadUint64 (& s .nInt )
28+ return N (fval + float64 (ival ))
1929}
2030
2131// valueMap is the storage for sums.
2232type valueMap [N int64 | float64 ] struct {
23- sync.Mutex
33+ sync.RWMutex
2434 newRes func (attribute.Set ) FilteredExemplarReservoir [N ]
2535 limit limiter [sumValue [N ]]
26- values map [attribute.Distinct ]sumValue [N ]
36+ values map [attribute.Distinct ]* sumValue [N ]
2737}
2838
2939func newValueMap [N int64 | float64 ](limit int , r func (attribute.Set ) FilteredExemplarReservoir [N ]) * valueMap [N ] {
3040 return & valueMap [N ]{
3141 newRes : r ,
3242 limit : newLimiter [sumValue [N ]](limit ),
33- values : make (map [attribute.Distinct ]sumValue [N ]),
43+ values : make (map [attribute.Distinct ]* sumValue [N ]),
3444 }
3545}
3646
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-
47+ func (s * valueMap [N ]) getOrCreateSumValue (fltrAttr attribute.Set , droppedAttr []attribute.KeyValue ) * sumValue [N ] {
48+ s .RLock ()
4149 attr := s .limit .Attributes (fltrAttr , s .values )
4250 v , ok := s .values [attr .Equivalent ()]
51+ s .RUnlock ()
4352 if ! ok {
44- v .res = s .newRes (attr )
53+ v = & sumValue [N ]{
54+ res : s .newRes (attr ),
55+ attrs : attr ,
56+ }
57+ s .Lock ()
58+ s .values [attr .Equivalent ()] = v
59+ s .Unlock ()
4560 }
61+ return v
62+ }
4663
47- v . attrs = attr
48- v . n += value
64+ func ( s * valueMap [ N ]) measure ( ctx context. Context , value N , fltrAttr attribute. Set , droppedAttr []attribute. KeyValue ) {
65+ v := s . getOrCreateSumValue ( fltrAttr , droppedAttr )
4966 v .res .Offer (ctx , value , droppedAttr )
5067
51- s .values [attr .Equivalent ()] = v
68+ ival := uint64 (value )
69+ // This case is where the value is an int, or if it is a whole-numbered float.
70+ if float64 (ival ) == float64 (value ) {
71+ atomic .AddUint64 (& v .nInt , ival )
72+ return
73+ }
74+
75+ // Value must be a float below.
76+ for {
77+ oldBits := atomic .LoadUint64 (& v .nFloatBits )
78+ newBits := math .Float64bits (math .Float64frombits (oldBits ) + float64 (value ))
79+ if atomic .CompareAndSwapUint64 (& v .nFloatBits , oldBits , newBits ) {
80+ return
81+ }
82+ }
5283}
5384
5485// newSum returns an aggregator that summarizes a set of measurements as their
@@ -92,7 +123,7 @@ func (s *sum[N]) delta(
92123 dPts [i ].Attributes = val .attrs
93124 dPts [i ].StartTime = s .start
94125 dPts [i ].Time = t
95- dPts [i ].Value = val .n
126+ dPts [i ].Value = val .val ()
96127 collectExemplars (& dPts [i ].Exemplars , val .res .Collect )
97128 i ++
98129 }
@@ -129,7 +160,7 @@ func (s *sum[N]) cumulative(
129160 dPts [i ].Attributes = value .attrs
130161 dPts [i ].StartTime = s .start
131162 dPts [i ].Time = t
132- dPts [i ].Value = value .n
163+ dPts [i ].Value = value .val ()
133164 collectExemplars (& dPts [i ].Exemplars , value .res .Collect )
134165 // TODO (#3006): This will use an unbounded amount of memory if there
135166 // are unbounded number of attribute sets being aggregated. Attribute
@@ -189,15 +220,15 @@ func (s *precomputedSum[N]) delta(
189220
190221 var i int
191222 for key , value := range s .values {
192- delta := value .n - s .reported [key ]
223+ delta := value .val () - s .reported [key ]
193224
194225 dPts [i ].Attributes = value .attrs
195226 dPts [i ].StartTime = s .start
196227 dPts [i ].Time = t
197228 dPts [i ].Value = delta
198229 collectExemplars (& dPts [i ].Exemplars , value .res .Collect )
199230
200- newReported [key ] = value .n
231+ newReported [key ] = value .val ()
201232 i ++
202233 }
203234 // Unused attribute sets do not report.
@@ -234,7 +265,7 @@ func (s *precomputedSum[N]) cumulative(
234265 dPts [i ].Attributes = val .attrs
235266 dPts [i ].StartTime = s .start
236267 dPts [i ].Time = t
237- dPts [i ].Value = val .n
268+ dPts [i ].Value = val .val ()
238269 collectExemplars (& dPts [i ].Exemplars , val .res .Collect )
239270
240271 i ++
0 commit comments