OLD | NEW |
---|---|
1 package analysis | 1 package analysis |
2 | 2 |
3 import ( | 3 import ( |
4 "sync" | 4 "sync" |
5 "time" | 5 "time" |
6 | 6 |
7 "github.com/golang/glog" | 7 "github.com/golang/glog" |
8 "github.com/rcrowley/go-metrics" | 8 "github.com/rcrowley/go-metrics" |
9 | 9 |
10 "skia.googlesource.com/buildbot.git/go/util" | 10 "skia.googlesource.com/buildbot.git/go/util" |
11 "skia.googlesource.com/buildbot.git/golden/go/diff" | 11 "skia.googlesource.com/buildbot.git/golden/go/diff" |
12 "skia.googlesource.com/buildbot.git/golden/go/expstorage" | 12 "skia.googlesource.com/buildbot.git/golden/go/expstorage" |
13 "skia.googlesource.com/buildbot.git/golden/go/types" | 13 "skia.googlesource.com/buildbot.git/golden/go/types" |
14 ptypes "skia.googlesource.com/buildbot.git/perf/go/types" | 14 ptypes "skia.googlesource.com/buildbot.git/perf/go/types" |
15 ) | 15 ) |
16 | 16 |
17 // Stores a Trace with labels and digests in memory. CommitIds, Digests and | 17 // Stores a Trace with labels and digests in memory. CommitIds, Digests and |
18 // Labels are of the same length, identical indices refer to the same digest. | 18 // Labels are of the same length, identical indices refer to the same digest. |
19 type LabeledTrace struct { | 19 type LabeledTrace struct { |
20 » Params map[string]string `json:"params"` | 20 » Params map[string]string |
21 » CommitIds []int `json:"commitIds"` | 21 » CommitIds []int |
22 » Digests []string `json:"digests"` | 22 » Digests []string |
23 » Labels []types.Label `json:"labels` | 23 » Labels []types.Label |
24 } | 24 } |
25 | 25 |
26 func NewLabeledTrace(params map[string]string, capacity int) *LabeledTrace { | 26 func NewLabeledTrace(params map[string]string, capacity int) *LabeledTrace { |
27 return &LabeledTrace{ | 27 return &LabeledTrace{ |
28 Params: params, | 28 Params: params, |
29 CommitIds: make([]int, 0, capacity), | 29 CommitIds: make([]int, 0, capacity), |
30 Digests: make([]string, 0, capacity), | 30 Digests: make([]string, 0, capacity), |
31 Labels: make([]types.Label, 0, capacity), | 31 Labels: make([]types.Label, 0, capacity), |
32 } | 32 } |
33 } | 33 } |
34 | 34 |
35 // Add the given tripples of commitIds, digests and labels to this LabeledTrace. | 35 // Add the given tripples of commitIds, digests and labels to this LabeledTrace. |
36 func (lt *LabeledTrace) addLabeledDigests(commitIds []int, digests []string, lab els []types.Label) { | 36 func (lt *LabeledTrace) addLabeledDigests(commitIds []int, digests []string, lab els []types.Label) { |
37 lt.CommitIds = append(lt.CommitIds, commitIds...) | 37 lt.CommitIds = append(lt.CommitIds, commitIds...) |
38 lt.Digests = append(lt.Digests, digests...) | 38 lt.Digests = append(lt.Digests, digests...) |
39 lt.Labels = append(lt.Labels, labels...) | 39 lt.Labels = append(lt.Labels, labels...) |
40 } | 40 } |
41 | 41 |
42 // Aggregates the Traces in tile and provides the commits that the | 42 // Aggregates the Traces in tile and provides the commits that the |
43 // CommitIds in LabeledTrace refer to. | 43 // CommitIds in LabeledTrace refer to. |
44 // LabeledTile and LabeledTrace are used to store the cannonical information | |
45 // extracted from the tiles. The (redundant) output data is derived from these. | |
44 type LabeledTile struct { | 46 type LabeledTile struct { |
45 » Commits []*ptypes.Commit `json:"commits"` | 47 » Commits []*ptypes.Commit |
46 | 48 |
47 // Traces are indexed by the primary key (test name). This is somewhat | 49 // Traces are indexed by the primary key (test name). This is somewhat |
48 // redundant, but this also output format. | 50 // redundant, but this also output format. |
49 » Traces map[string][]*LabeledTrace `json:"traces"` | 51 » Traces map[string][]*LabeledTrace |
50 } | 52 } |
51 | 53 |
52 func NewLabeledTile() *LabeledTile { | 54 func NewLabeledTile() *LabeledTile { |
53 return &LabeledTile{ | 55 return &LabeledTile{ |
54 Commits: []*ptypes.Commit{}, | 56 Commits: []*ptypes.Commit{}, |
55 Traces: map[string][]*LabeledTrace{}, | 57 Traces: map[string][]*LabeledTrace{}, |
56 } | 58 } |
57 } | 59 } |
58 | 60 |
59 // Utility function that returns the testName and a labeled trace for the given | 61 // Utility function that returns the testName and a labeled trace for the given |
(...skipping 14 matching lines...) Expand all Loading... | |
74 } | 76 } |
75 } | 77 } |
76 | 78 |
77 // If we cannot find the trace in our set of tests we are adding a new | 79 // If we cannot find the trace in our set of tests we are adding a new |
78 // labeled trace. | 80 // labeled trace. |
79 newLT := NewLabeledTrace(params, trace.Len()) | 81 newLT := NewLabeledTrace(params, trace.Len()) |
80 t.Traces[pKey] = append(t.Traces[pKey], newLT) | 82 t.Traces[pKey] = append(t.Traces[pKey], newLT) |
81 return pKey, newLT | 83 return pKey, newLT |
82 } | 84 } |
83 | 85 |
86 // GUITileCounts is an output type for the aggregated label counts. | |
87 // The tupples in Counts store: untriaged, positive, negatives | |
88 type GUITileCounts struct { | |
89 Commits []*ptypes.Commit `json:"commits"` | |
90 Counts map[string][][3]int64 `json:"counts"` | |
jcgregorio
2014/10/17 18:07:52
[3]int64 is a little ambiguous as far as figuring
stephana
2014/10/17 20:01:45
Done.
| |
91 } | |
92 | |
93 // GUITestCounts is an output type for a single test that contains the | |
94 // aggregated counts over all traces and invidual trace labels. | |
95 type GUITestCounts struct { | |
96 Commits []*ptypes.Commit `json:"commits"` | |
97 Aggregated [][3]int64 `json:"aggregated"` | |
98 Traces []*GUILabeledTrace `json:"traces"` | |
99 } | |
100 | |
101 // GUILabeledTrace is an output type for the labels of a trace. | |
102 type GUILabeledTrace struct { | |
103 Params map[string]string `json:"params"` | |
104 | |
105 // Contains (commitId, lable) pairs. | |
106 Labels [][2]uint64 `json:"labels"` | |
jcgregorio
2014/10/17 18:07:52
Why not map[int64]int64 or []struct{ ID int64, Lab
stephana
2014/10/17 20:01:45
Done.
| |
107 } | |
108 | |
84 // Analyzer continuously manages the tasks, like pollint for new traces | 109 // Analyzer continuously manages the tasks, like pollint for new traces |
85 // on disk, etc. | 110 // on disk, etc. |
86 type Analyzer struct { | 111 type Analyzer struct { |
87 expStore expstorage.ExpectationsStore | 112 expStore expstorage.ExpectationsStore |
88 diffStore diff.DiffStore | 113 diffStore diff.DiffStore |
89 tileStore ptypes.TileStore | 114 tileStore ptypes.TileStore |
90 | 115 |
116 // Canonical data structure to hold our information about commits, diges ts | |
117 // and labels. | |
91 currentTile *LabeledTile | 118 currentTile *LabeledTile |
92 | 119 |
93 » // Lock to protect the expectations and the current labeled tile. | 120 » // Output data structures that are derived from currentTile. |
121 » currentTileCounts *GUITileCounts | |
122 » currentTestCounts map[string]*GUITestCounts | |
123 | |
124 » // Lock to protect the expectations and current* variables. | |
94 mutex sync.Mutex | 125 mutex sync.Mutex |
95 } | 126 } |
96 | 127 |
97 func NewAnalyzer(expStore expstorage.ExpectationsStore, tileStore ptypes.TileSto re, diffStore diff.DiffStore, timeBetweenPolls time.Duration) *Analyzer { | 128 func NewAnalyzer(expStore expstorage.ExpectationsStore, tileStore ptypes.TileSto re, diffStore diff.DiffStore, timeBetweenPolls time.Duration) *Analyzer { |
98 result := &Analyzer{ | 129 result := &Analyzer{ |
99 expStore: expStore, | 130 expStore: expStore, |
100 diffStore: diffStore, | 131 diffStore: diffStore, |
101 tileStore: tileStore, | 132 tileStore: tileStore, |
102 | 133 |
103 currentTile: NewLabeledTile(), | 134 currentTile: NewLabeledTile(), |
104 } | 135 } |
105 | 136 |
106 go result.loop(timeBetweenPolls) | 137 go result.loop(timeBetweenPolls) |
107 return result | 138 return result |
108 } | 139 } |
109 | 140 |
110 // Returns an entire Tile which is a collection of 'traces' over a series of | 141 // Returns an entire Tile which is a collection of 'traces' over a series of |
111 // of commits. Each trace contains the digests and their labels based on | 142 // of commits. Each trace contains the digests and their labels based on |
112 // out knowledge base about digests (expectations). | 143 // out knowledge base about digests (expectations). |
113 func (a *Analyzer) GetLabeledTile() *LabeledTile { | 144 func (a *Analyzer) GetTileCounts() (*GUITileCounts, error) { |
114 a.mutex.Lock() | 145 a.mutex.Lock() |
115 defer a.mutex.Unlock() | 146 defer a.mutex.Unlock() |
116 | 147 |
117 » return a.currentTile | 148 » return a.currentTileCounts, nil |
118 } | 149 } |
119 | 150 |
120 func (a *Analyzer) GetLabeledTraces(testName string) []*LabeledTrace { | 151 func (a *Analyzer) GetTestCounts(testName string) (*GUITestCounts, error) { |
121 a.mutex.Lock() | 152 a.mutex.Lock() |
122 defer a.mutex.Unlock() | 153 defer a.mutex.Unlock() |
123 | 154 |
124 » return a.currentTile.Traces[testName] | 155 » return a.currentTestCounts[testName], nil |
125 } | 156 } |
126 | 157 |
127 func (a *Analyzer) SetDigestLabels(labeledTestDigests map[string]types.TestClass ification, userId string) (map[string][]*LabeledTrace, error) { | 158 func (a *Analyzer) SetDigestLabels(labeledTestDigests map[string]types.TestClass ification, userId string) (map[string][]*LabeledTrace, error) { |
128 a.mutex.Lock() | 159 a.mutex.Lock() |
129 defer a.mutex.Unlock() | 160 defer a.mutex.Unlock() |
130 | 161 |
131 expectations, err := a.expStore.Get(true) | 162 expectations, err := a.expStore.Get(true) |
132 if err != nil { | 163 if err != nil { |
133 return nil, err | 164 return nil, err |
134 } | 165 } |
(...skipping 18 matching lines...) Expand all Loading... | |
153 for { | 184 for { |
154 glog.Info("Reading tiles ... ") | 185 glog.Info("Reading tiles ... ") |
155 | 186 |
156 // Load the tile and process it. | 187 // Load the tile and process it. |
157 tile, err := a.tileStore.Get(0, -1) | 188 tile, err := a.tileStore.Get(0, -1) |
158 if err != nil { | 189 if err != nil { |
159 glog.Errorf("Error reading tile store: %s\n", err.Error( )) | 190 glog.Errorf("Error reading tile store: %s\n", err.Error( )) |
160 errorTileLoadingCounter.Inc(1) | 191 errorTileLoadingCounter.Inc(1) |
161 } else { | 192 } else { |
162 newLabeledTile := a.processTile(tile) | 193 newLabeledTile := a.processTile(tile) |
194 newTileCounts, newTestCounts := a.getOutputCounts(newLab eledTile) | |
195 | |
163 a.mutex.Lock() | 196 a.mutex.Lock() |
164 a.currentTile = newLabeledTile | 197 a.currentTile = newLabeledTile |
198 a.currentTileCounts = newTileCounts | |
199 a.currentTestCounts = newTestCounts | |
165 a.mutex.Unlock() | 200 a.mutex.Unlock() |
166 } | 201 } |
167 runsCounter.Inc(1) | 202 runsCounter.Inc(1) |
168 | 203 |
169 // Sleep for a while until the next poll. | 204 // Sleep for a while until the next poll. |
170 time.Sleep(timeBetweenPolls) | 205 time.Sleep(timeBetweenPolls) |
171 } | 206 } |
172 } | 207 } |
173 | 208 |
174 // Process a tile segment and add it to the currentTile. | 209 // Process a tile segment and add it to the currentTile. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 for idx, digest := range digests { | 276 for idx, digest := range digests { |
242 if test, ok := expectations.Tests[testName]; ok { | 277 if test, ok := expectations.Tests[testName]; ok { |
243 if foundLabel, ok := test[digest]; ok { | 278 if foundLabel, ok := test[digest]; ok { |
244 targetLabels[idx] = foundLabel | 279 targetLabels[idx] = foundLabel |
245 } | 280 } |
246 } | 281 } |
247 } | 282 } |
248 | 283 |
249 return nil | 284 return nil |
250 } | 285 } |
286 | |
287 // Derive the output counts from the given labeled tile. | |
288 func (a *Analyzer) getOutputCounts(labeledTile *LabeledTile) (*GUITileCounts, ma p[string]*GUITestCounts) { | |
289 // Stores the aggregated counts of a tile for each test. | |
290 tileCountsMap := make(map[string][][3]int64, len(labeledTile.Traces)) | |
291 | |
292 // Stores the aggregated counts for each test and individual trace infor mation. | |
293 testCountsMap := make(map[string]*GUITestCounts, len(labeledTile.Traces) ) | |
294 | |
295 for testName, testTraces := range labeledTile.Traces { | |
296 acc := make([][3]int64, len(labeledTile.Commits)) | |
297 tempTraces := make([]*GUILabeledTrace, 0, len(testTraces)) | |
298 | |
299 for _, oneTrace := range testTraces { | |
300 tempTrace := &GUILabeledTrace{ | |
301 Params: oneTrace.Params, | |
302 Labels: make([][2]uint64, len(oneTrace.CommitIds )), | |
303 } | |
304 | |
305 for i, ci := range oneTrace.CommitIds { | |
306 // Increment the tuple element based on Label co nstant values. | |
307 acc[ci][oneTrace.Labels[i]]++ | |
308 tempTrace.Labels[i][0] = uint64(ci) | |
309 tempTrace.Labels[i][1] = uint64(oneTrace.Labels[ i]) | |
310 } | |
311 } | |
312 | |
313 tileCountsMap[testName] = acc | |
314 testCountsMap[testName] = &GUITestCounts{ | |
315 Commits: labeledTile.Commits, | |
316 Aggregated: acc, | |
317 Traces: tempTraces, | |
318 } | |
319 } | |
320 | |
321 tileCounts := &GUITileCounts{ | |
322 Commits: labeledTile.Commits, | |
323 Counts: tileCountsMap, | |
324 } | |
325 | |
326 return tileCounts, testCountsMap | |
327 } | |
OLD | NEW |