@@ -13,59 +13,55 @@ import (
13
13
"gonum.org/v1/gonum/mat"
14
14
)
15
15
16
- type OverrideInfo struct {
17
- OverrideMainline bool `bson:"override_mainline"`
18
- BaseOrder any `bson:"base_order"`
19
- Reason any `bson:"reason"`
20
- User any `bson:"user"`
16
+ // RawData defines the shape of the data in the raw_results collection.
17
+ // raw_results stores results by benchmark, which holds the values of all its measurements.
18
+ // A single measurement from a single benchmark is called a microbenchmark.
19
+ type RawData struct {
20
+ Info Info
21
+ CreatedAt any `bson:"created_at"`
22
+ CompletedAt any `bson:"completed_at"`
23
+ Rollups Rollups // List of all measurement results
24
+ FailedRollupAttempts int64 `bson:"failed_rollup_attempts"`
21
25
}
22
26
23
27
type Info struct {
24
28
Project string `bson:"project"`
25
- Version string `bson:"version"`
29
+ Version string `bson:"version"` // Evergreen version that produced the results
26
30
Variant string `bson:"variant"`
27
31
Order int64 `bson:"order"`
28
32
TaskName string `bson:"task_name"`
29
33
TaskID string `bson:"task_id"`
30
34
Execution int64 `bson:"execution"`
31
35
Mainline bool `bson:"mainline"`
32
36
OverrideInfo OverrideInfo
33
- TestName string `bson:"test_name"`
37
+ TestName string `bson:"test_name"` // Benchmark name
34
38
Args map [string ]any `bson:"args"`
35
39
}
36
40
37
- type Stat struct {
38
- Name string `bson:"name"`
39
- Val float64 `bson:"val"`
40
- Metadata any `bson:"metadata"`
41
+ type OverrideInfo struct {
42
+ OverrideMainline bool `bson:"override_mainline"`
43
+ BaseOrder any `bson:"base_order"`
44
+ Reason any `bson:"reason"`
45
+ User any `bson:"user"`
41
46
}
42
47
43
48
type Rollups struct {
44
49
Stats []Stat
45
50
}
46
51
47
- type RawData struct {
48
- Info Info
49
- CreatedAt any `bson:"created_at"`
50
- CompletedAt any `bson:"completed_at"`
51
- Rollups Rollups
52
- FailedRollupAttempts int64 `bson:"failed_rollup_attempts"`
53
- }
54
-
55
- type TimeSeriesInfo struct {
56
- Project string `bson:"project"`
57
- Variant string `bson:"variant"`
58
- Task string `bson:"task"`
59
- Test string `bson:"test"`
60
- Measurement string `bson:"measurement"`
61
- Args map [string ]any `bson:"args"`
52
+ type Stat struct {
53
+ Name string `bson:"name"` // Measurement name
54
+ Val float64 `bson:"val"` // Microbenchmark result
55
+ Metadata any `bson:"metadata"`
62
56
}
63
57
58
+ // StableRegion defines the shape of the data in the stable_regions collection.
59
+ // A stable region is a group of consecutive microbenchmark values between two change points.
64
60
type StableRegion struct {
65
61
TimeSeriesInfo TimeSeriesInfo
66
62
Start any `bson:"start"`
67
63
End any `bson:"end"`
68
- Values []float64 `bson:"values"`
64
+ Values []float64 `bson:"values"` // All microbenchmark values that makes up the stable region
69
65
StartOrder int64 `bson:"start_order"`
70
66
EndOrder int64 `bson:"end_order"`
71
67
Mean float64 `bson:"mean"`
@@ -76,36 +72,50 @@ type StableRegion struct {
76
72
CoefficientOfVariation float64 `bson:"coefficient_of_variation"`
77
73
LastSuccessfulUpdate any `bson:"last_successful_update"`
78
74
Last bool `bson:"last"`
79
- Contexts []any `bson:"contexts"`
75
+ Contexts []any `bson:"contexts"` // Performance context (e.g. "Go Driver perf comp")
76
+ }
77
+
78
+ type TimeSeriesInfo struct {
79
+ Project string `bson:"project"`
80
+ Variant string `bson:"variant"`
81
+ Task string `bson:"task"`
82
+ Test string `bson:"test"` // Benchmark name
83
+ Measurement string `bson:"measurement"` // Measurement name
84
+ Args map [string ]any `bson:"args"`
80
85
}
81
86
87
+ // EnergyStats stores the calculated energy statistics for a patch version's specific
88
+ // microbenchmark compared to the mainline's stable region for that same microbenchmark.
82
89
type EnergyStats struct {
83
90
Project string
84
91
Benchmark string
85
92
Measurement string
86
- PatchVersion string
87
- StableRegion StableRegion
88
- MeasurementVal float64
93
+ PatchVersion string // Evergreen version that produced the results
94
+ StableRegion StableRegion // Latest stable region from the mainline this patch is comparing against
95
+ MeasurementVal float64 // Microbenchmark result of the patch version
89
96
PercentChange float64
90
97
EnergyStatistic float64
91
98
TestStatistic float64
92
99
HScore float64
93
100
ZScore float64
94
101
}
95
102
103
+ // CompareResult is the collection of the energy statistics of all microbenchmarks with
104
+ // statistically significant changes for this patch.
96
105
type CompareResult struct {
97
- CommitSHA string
98
- MainlineCommit string
99
- Version string
106
+ CommitSHA string // Head commit SHA
107
+ MainlineCommit string // Base commit SHA
108
+ Version string // Evergreen patch version
100
109
SigEnergyStats []EnergyStats
101
110
}
102
111
112
+ // Performance analytics node db and collection names
103
113
const expandedMetricsDB = "expanded_metrics"
104
114
const rawResultsColl = "raw_results"
105
115
const stableRegionsColl = "stable_regions"
106
116
107
117
// Compare will return statistical results for a patch version using the
108
- // stable region defined by the performance analyzer cluster.
118
+ // stable region defined by the performance analytics cluster.
109
119
func Compare (ctx context.Context , versionID string , perfAnalyzerConnString string , project string , perfContext string ) (* CompareResult , error ) {
110
120
111
121
// Connect to analytics node
@@ -156,6 +166,7 @@ func Compare(ctx context.Context, versionID string, perfAnalyzerConnString strin
156
166
return & compareResult , nil
157
167
}
158
168
169
+ // Gets all raw benchmark data for a specific Evergreen version.
159
170
func findRawData (ctx context.Context , project string , version string , coll * mongo.Collection ) ([]RawData , error ) {
160
171
filter := bson.D {
161
172
{"info.project" , project },
@@ -194,7 +205,7 @@ func findRawData(ctx context.Context, project string, version string, coll *mong
194
205
return rawData , err
195
206
}
196
207
197
- // Find the most recent stable region of the mainline version for a specific test/measurement
208
+ // Finds the most recent stable region of the mainline version for a specific microbenchmark.
198
209
func findLastStableRegion (ctx context.Context , project string , testname string , measurement string , coll * mongo.Collection , perfContext string ) (* StableRegion , error ) {
199
210
filter := bson.D {
200
211
{"time_series_info.project" , project },
@@ -216,7 +227,7 @@ func findLastStableRegion(ctx context.Context, project string, testname string,
216
227
return sr , nil
217
228
}
218
229
219
- // For a specific test and measurement
230
+ // Calculate the energy statistics for all measurements in a benchmark.
220
231
func getEnergyStatsForOneBenchmark (ctx context.Context , rd RawData , coll * mongo.Collection , perfContext string ) ([]* EnergyStats , error ) {
221
232
testname := rd .Info .TestName
222
233
var energyStats []* EnergyStats
@@ -241,7 +252,7 @@ func getEnergyStatsForOneBenchmark(ctx context.Context, rd RawData, coll *mongo.
241
252
stableRegionVec := mat .NewDense (len (stableRegion .Values ), 1 , stableRegion .Values )
242
253
measValVec := mat .NewDense (1 , 1 , []float64 {measVal }) // singleton
243
254
244
- estat , tstat , hscore , err := getEnergyStatistics (stableRegionVec , measValVec )
255
+ estat , tstat , hscore , err := calcEnergyStatistics (stableRegionVec , measValVec )
245
256
if err != nil {
246
257
log .Fatalf (
247
258
"Could not calculate energy stats for test %q, measurement %q: %v" ,
@@ -251,8 +262,8 @@ func getEnergyStatsForOneBenchmark(ctx context.Context, rd RawData, coll *mongo.
251
262
)
252
263
}
253
264
254
- zscore := getZScore (measVal , stableRegion .Mean , stableRegion .Std )
255
- pChange := getPercentageChange (measVal , stableRegion .Mean )
265
+ zscore := calcZScore (measVal , stableRegion .Mean , stableRegion .Std )
266
+ pChange := calcPercentChange (measVal , stableRegion .Mean )
256
267
257
268
es := EnergyStats {
258
269
Project : project ,
@@ -290,7 +301,7 @@ func getEnergyStatsForAllBenchMarks(ctx context.Context, patchRawData []RawData,
290
301
return allEnergyStats , nil
291
302
}
292
303
293
- func getStatSigBenchmarks (energyStats []* EnergyStats ) []EnergyStats { // TODO
304
+ func getStatSigBenchmarks (energyStats []* EnergyStats ) []EnergyStats {
294
305
295
306
var significantEnergyStats []EnergyStats
296
307
for _ , es := range energyStats {
@@ -308,7 +319,7 @@ func getStatSigBenchmarks(energyStats []*EnergyStats) []EnergyStats { // TODO
308
319
309
320
// Given two matrices, this function returns
310
321
// (e, t, h) = (E-statistic, test statistic, e-coefficient of inhomogeneity)
311
- func getEnergyStatistics (x , y * mat.Dense ) (float64 , float64 , float64 , error ) {
322
+ func calcEnergyStatistics (x , y * mat.Dense ) (float64 , float64 , float64 , error ) {
312
323
xrows , xcols := x .Dims ()
313
324
yrows , ycols := y .Dims ()
314
325
@@ -324,7 +335,7 @@ func getEnergyStatistics(x, y *mat.Dense) (float64, float64, float64, error) {
324
335
325
336
var A float64 // E|X-Y|
326
337
if xrowsf > 0 && yrowsf > 0 {
327
- dist , err := getDistance (x , y )
338
+ dist , err := calcDistance (x , y )
328
339
if err != nil {
329
340
return 0 , 0 , 0 , err
330
341
}
@@ -335,7 +346,7 @@ func getEnergyStatistics(x, y *mat.Dense) (float64, float64, float64, error) {
335
346
336
347
var B float64 // E|X-X'|
337
348
if xrowsf > 0 {
338
- dist , err := getDistance (x , x )
349
+ dist , err := calcDistance (x , x )
339
350
if err != nil {
340
351
return 0 , 0 , 0 , err
341
352
}
@@ -346,7 +357,7 @@ func getEnergyStatistics(x, y *mat.Dense) (float64, float64, float64, error) {
346
357
347
358
var C float64 // E|Y-Y'|
348
359
if yrowsf > 0 {
349
- dist , err := getDistance (y , y )
360
+ dist , err := calcDistance (y , y )
350
361
if err != nil {
351
362
return 0 , 0 , 0 , err
352
363
}
@@ -368,7 +379,7 @@ func getEnergyStatistics(x, y *mat.Dense) (float64, float64, float64, error) {
368
379
369
380
// Given two vectors (expected 1 col),
370
381
// this function returns the sum of distances between each pair.
371
- func getDistance (x , y * mat.Dense ) (float64 , error ) {
382
+ func calcDistance (x , y * mat.Dense ) (float64 , error ) {
372
383
xrows , xcols := x .Dims ()
373
384
yrows , ycols := y .Dims ()
374
385
@@ -386,16 +397,16 @@ func getDistance(x, y *mat.Dense) (float64, error) {
386
397
return sum , nil
387
398
}
388
399
389
- // Get Z score for result x, compared to mean u and st dev o .
390
- func getZScore (x , mu , sigma float64 ) float64 {
400
+ // Calculate the Z score for result x, compared to mean mu and st dev sigma .
401
+ func calcZScore (x , mu , sigma float64 ) float64 {
391
402
if sigma == 0 {
392
403
return math .NaN ()
393
404
}
394
405
return (x - mu ) / sigma
395
406
}
396
407
397
- // Get percentage change for result x compared to mean u .
398
- func getPercentageChange (x , mu float64 ) float64 {
408
+ // Calculate the percentage change for result x compared to mean mu .
409
+ func calcPercentChange (x , mu float64 ) float64 {
399
410
if mu == 0 {
400
411
return math .NaN ()
401
412
}
0 commit comments