github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/dashboard/app/build/perf_learn.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build appengine 6 7 package build 8 9 import ( 10 "bytes" 11 "fmt" 12 "html/template" 13 "net/http" 14 "sort" 15 16 "appengine" 17 "appengine/datastore" 18 ) 19 20 func init() { 21 handleFunc("/perflearn", perfLearnHandler) 22 } 23 24 const ( 25 learnPercentile = 0.95 26 learnSignalMultiplier = 1.1 27 learnMinSignal = 0.5 28 ) 29 30 func perfLearnHandler(w http.ResponseWriter, r *http.Request) { 31 d := dashboardForRequest(r) 32 c := d.Context(appengine.NewContext(r)) 33 34 pc, err := GetPerfConfig(c, r) 35 if err != nil { 36 logErr(w, r, err) 37 return 38 } 39 40 p, err := GetPackage(c, "") 41 if err != nil { 42 logErr(w, r, err) 43 return 44 } 45 46 update := r.FormValue("update") != "" 47 noise := make(map[string]string) 48 49 data := &perfLearnData{} 50 51 commits, err := GetCommits(c, 0, p.NextNum) 52 if err != nil { 53 logErr(w, r, err) 54 return 55 } 56 57 for _, builder := range pc.BuildersForBenchmark("") { 58 for _, benchmark := range pc.BenchmarksForBuilder(builder) { 59 for _, metric := range pc.MetricsForBenchmark(benchmark) { 60 for _, procs := range pc.ProcList(builder) { 61 values, err := GetPerfMetricsForCommits(c, builder, fmt.Sprintf("%v-%v", benchmark, procs), metric, 0, p.NextNum) 62 if err != nil { 63 logErr(w, r, err) 64 return 65 } 66 var dd []float64 67 last := uint64(0) 68 for i, v := range values { 69 if v == 0 { 70 if com := commits[i]; com == nil || com.NeedsBenchmarking { 71 last = 0 72 } 73 continue 74 } 75 if last != 0 { 76 v1 := v 77 if v1 < last { 78 v1, last = last, v1 79 } 80 diff := float64(v1)/float64(last)*100 - 100 81 dd = append(dd, diff) 82 } 83 last = v 84 } 85 if len(dd) == 0 { 86 continue 87 } 88 sort.Float64s(dd) 89 90 baseIdx := int(float64(len(dd)) * learnPercentile) 91 baseVal := dd[baseIdx] 92 signalVal := baseVal * learnSignalMultiplier 93 if signalVal < learnMinSignal { 94 signalVal = learnMinSignal 95 } 96 signalIdx := -1 97 noiseNum := 0 98 signalNum := 0 99 100 var diffs []*perfLearnDiff 101 for i, d := range dd { 102 if d > 3*signalVal { 103 d = 3 * signalVal 104 } 105 diffs = append(diffs, &perfLearnDiff{Num: i, Val: d}) 106 if signalIdx == -1 && d >= signalVal { 107 signalIdx = i 108 } 109 if d < signalVal { 110 noiseNum++ 111 } else { 112 signalNum++ 113 } 114 } 115 diffs[baseIdx].Hint = "95%" 116 if signalIdx != -1 { 117 diffs[signalIdx].Hint = "signal" 118 } 119 diffs = diffs[len(diffs)*4/5:] 120 name := fmt.Sprintf("%v/%v-%v/%v", builder, benchmark, procs, metric) 121 data.Entries = append(data.Entries, &perfLearnEntry{len(data.Entries), name, baseVal, noiseNum, signalVal, signalNum, diffs}) 122 123 if len(dd) >= 100 || r.FormValue("force") != "" { 124 nname := fmt.Sprintf("%v|%v-%v", builder, benchmark, procs) 125 n := noise[nname] + fmt.Sprintf("|%v=%.2f", metric, signalVal) 126 noise[nname] = n 127 } 128 } 129 } 130 } 131 } 132 133 if update { 134 var noiseLevels []string 135 for k, v := range noise { 136 noiseLevels = append(noiseLevels, k+v) 137 } 138 tx := func(c appengine.Context) error { 139 pc, err := GetPerfConfig(c, r) 140 if err != nil { 141 return err 142 } 143 pc.NoiseLevels = noiseLevels 144 if _, err := datastore.Put(c, PerfConfigKey(c), pc); err != nil { 145 return fmt.Errorf("putting PerfConfig: %v", err) 146 } 147 return nil 148 } 149 if err := datastore.RunInTransaction(c, tx, nil); err != nil { 150 logErr(w, r, err) 151 return 152 } 153 } 154 155 var buf bytes.Buffer 156 if err := perfLearnTemplate.Execute(&buf, data); err != nil { 157 logErr(w, r, err) 158 return 159 } 160 161 buf.WriteTo(w) 162 } 163 164 var perfLearnTemplate = template.Must( 165 template.New("perf_learn.html").Funcs(tmplFuncs).ParseFiles("build/perf_learn.html"), 166 ) 167 168 type perfLearnData struct { 169 Entries []*perfLearnEntry 170 } 171 172 type perfLearnEntry struct { 173 Num int 174 Name string 175 BaseVal float64 176 NoiseNum int 177 SignalVal float64 178 SignalNum int 179 Diffs []*perfLearnDiff 180 } 181 182 type perfLearnDiff struct { 183 Num int 184 Val float64 185 Hint string 186 }