@@ -49,9 +49,10 @@ const (
49
49
)
50
50
51
51
type timingAggregator struct {
52
- mu sync.Mutex
53
-
54
52
stage database.ProvisionerJobTimingStage
53
+
54
+ // Protects the stateLookup map.
55
+ lookupMu sync.Mutex
55
56
stateLookup map [uint64 ]* timingSpan
56
57
}
57
58
@@ -81,7 +82,7 @@ func (t *timingAggregator) ingest(ts time.Time, s *timingSpan) {
81
82
}
82
83
83
84
s .stage = t .stage
84
- ts = dbtime .Time (ts )
85
+ ts = dbtime .Time (ts . UTC () )
85
86
86
87
switch s .kind {
87
88
case timingApplyStart , timingProvisionStart , timingRefreshStart , timingInitStart , timingGraphStart :
@@ -98,21 +99,22 @@ func (t *timingAggregator) ingest(ts time.Time, s *timingSpan) {
98
99
return
99
100
}
100
101
101
- t .mu .Lock ()
102
+ t .lookupMu .Lock ()
102
103
// Memoize this span by its unique attributes and the determined state.
103
104
// This will be used in aggregate() to determine the duration of the resource action.
104
105
t .stateLookup [s .hashByState (s .state )] = s
105
- t .mu .Unlock ()
106
+ t .lookupMu .Unlock ()
106
107
}
107
108
108
109
// aggregate performs a pass through all memoized events to build up a slice of *proto.Timing instances which represent
109
110
// the total time taken to perform a certain action.
110
111
// The resulting slice of *proto.Timing is NOT sorted.
111
112
func (t * timingAggregator ) aggregate () []* proto.Timing {
112
- t .mu .Lock ()
113
- defer t .mu .Unlock ()
113
+ t .lookupMu .Lock ()
114
+ defer t .lookupMu .Unlock ()
114
115
115
- out := make ([]* proto.Timing , 0 , len (t .stateLookup ))
116
+ // Pre-allocate len(measurements)/2 since each timing will have one STARTED and one FAILED/COMPLETED entry.
117
+ out := make ([]* proto.Timing , 0 , len (t .stateLookup )/ 2 )
116
118
117
119
for _ , s := range t .stateLookup {
118
120
// We are only concerned here with failed or completed events.
0 commit comments