github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/dashboard/app/build/perf_graph.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 "strconv" 15 16 "appengine" 17 "appengine/datastore" 18 ) 19 20 func init() { 21 handleFunc("/perfgraph", perfGraphHandler) 22 } 23 24 func perfGraphHandler(w http.ResponseWriter, r *http.Request) { 25 d := dashboardForRequest(r) 26 c := d.Context(appengine.NewContext(r)) 27 pc, err := GetPerfConfig(c, r) 28 if err != nil { 29 logErr(w, r, err) 30 return 31 } 32 allBuilders := pc.BuildersForBenchmark("") 33 allBenchmarks := pc.BenchmarksForBuilder("") 34 allMetrics := pc.MetricsForBenchmark("") 35 allProcs := pc.ProcList("") 36 r.ParseForm() 37 selBuilders := r.Form["builder"] 38 selBenchmarks := r.Form["benchmark"] 39 selMetrics := r.Form["metric"] 40 selProcs := r.Form["procs"] 41 if len(selBuilders) == 0 { 42 selBuilders = append(selBuilders, allBuilders[0]) 43 } 44 if len(selBenchmarks) == 0 { 45 selBenchmarks = append(selBenchmarks, "json") 46 } 47 if len(selMetrics) == 0 { 48 selMetrics = append(selMetrics, "time") 49 } 50 if len(selProcs) == 0 { 51 selProcs = append(selProcs, "1") 52 } 53 commitFrom := r.FormValue("commit-from") 54 if commitFrom == "" { 55 commitFrom = lastRelease 56 } 57 commitTo := r.FormValue("commit-to") 58 if commitTo == "" { 59 commitTo = "tip" 60 } 61 // TODO(dvyukov): validate input 62 63 // Figure out start and end commit from commitFrom/commitTo. 64 startCommitNum := 0 65 endCommitNum := 0 66 { 67 comFrom := &Commit{Hash: knownTags[commitFrom]} 68 if err := datastore.Get(c, comFrom.Key(c), comFrom); err != nil { 69 logErr(w, r, err) 70 return 71 } 72 startCommitNum = comFrom.Num 73 74 retry: 75 if commitTo == "tip" { 76 p, err := GetPackage(c, "") 77 if err != nil { 78 logErr(w, r, err) 79 return 80 } 81 endCommitNum = p.NextNum 82 } else { 83 comTo := &Commit{Hash: knownTags[commitTo]} 84 if err := datastore.Get(c, comTo.Key(c), comTo); err != nil { 85 logErr(w, r, err) 86 return 87 } 88 endCommitNum = comTo.Num + 1 89 } 90 if endCommitNum <= startCommitNum { 91 // User probably selected from:go1.3 to:go1.2. Fix go1.2 to tip. 92 if commitTo == "tip" { 93 logErr(w, r, fmt.Errorf("no commits to display (%v-%v)", commitFrom, commitTo)) 94 return 95 } 96 commitTo = "tip" 97 goto retry 98 } 99 } 100 commitsToDisplay := endCommitNum - startCommitNum 101 102 present := func(set []string, s string) bool { 103 for _, s1 := range set { 104 if s1 == s { 105 return true 106 } 107 } 108 return false 109 } 110 111 cfg := &uiPerfConfig{} 112 for _, v := range allBuilders { 113 cfg.Builders = append(cfg.Builders, uiPerfConfigElem{v, present(selBuilders, v)}) 114 } 115 for _, v := range allBenchmarks { 116 cfg.Benchmarks = append(cfg.Benchmarks, uiPerfConfigElem{v, present(selBenchmarks, v)}) 117 } 118 for _, v := range allMetrics { 119 cfg.Metrics = append(cfg.Metrics, uiPerfConfigElem{v, present(selMetrics, v)}) 120 } 121 for _, v := range allProcs { 122 cfg.Procs = append(cfg.Procs, uiPerfConfigElem{strconv.Itoa(v), present(selProcs, strconv.Itoa(v))}) 123 } 124 for k := range knownTags { 125 cfg.CommitsFrom = append(cfg.CommitsFrom, uiPerfConfigElem{k, commitFrom == k}) 126 } 127 for k := range knownTags { 128 cfg.CommitsTo = append(cfg.CommitsTo, uiPerfConfigElem{k, commitTo == k}) 129 } 130 cfg.CommitsTo = append(cfg.CommitsTo, uiPerfConfigElem{"tip", commitTo == "tip"}) 131 132 var vals [][]float64 133 var hints [][]string 134 var annotations [][]string 135 var certainty [][]bool 136 var headers []string 137 commits2, err := GetCommits(c, startCommitNum, commitsToDisplay) 138 if err != nil { 139 logErr(w, r, err) 140 return 141 } 142 for _, builder := range selBuilders { 143 for _, metric := range selMetrics { 144 for _, benchmark := range selBenchmarks { 145 for _, procs := range selProcs { 146 benchProcs := fmt.Sprintf("%v-%v", benchmark, procs) 147 vv, err := GetPerfMetricsForCommits(c, builder, benchProcs, metric, startCommitNum, commitsToDisplay) 148 if err != nil { 149 logErr(w, r, err) 150 return 151 } 152 hasdata := false 153 for _, v := range vv { 154 if v != 0 { 155 hasdata = true 156 } 157 } 158 if hasdata { 159 noise := pc.NoiseLevel(builder, benchProcs, metric) 160 descBuilder := "/" + builder 161 descBenchmark := "/" + benchProcs 162 descMetric := "/" + metric 163 if len(selBuilders) == 1 { 164 descBuilder = "" 165 } 166 if len(selBenchmarks) == 1 && len(selProcs) == 1 { 167 descBenchmark = "" 168 } 169 if len(selMetrics) == 1 && (len(selBuilders) > 1 || len(selBenchmarks) > 1 || len(selProcs) > 1) { 170 descMetric = "" 171 } 172 desc := fmt.Sprintf("%v%v%v", descBuilder, descBenchmark, descMetric)[1:] 173 hh := make([]string, commitsToDisplay) 174 ann := make([]string, commitsToDisplay) 175 valf := make([]float64, commitsToDisplay) 176 cert := make([]bool, commitsToDisplay) 177 firstval := uint64(0) 178 lastval := uint64(0) 179 for i, v := range vv { 180 cert[i] = true 181 if v == 0 { 182 if lastval == 0 { 183 continue 184 } 185 cert[i] = false 186 v = lastval 187 } 188 if firstval == 0 { 189 firstval = v 190 } 191 valf[i] = float64(v) / float64(firstval) 192 if cert[i] { 193 d := "" 194 if lastval != 0 { 195 diff := perfDiff(lastval, v) 196 d = fmt.Sprintf(" (%+.02f%%)", diff) 197 if !isNoise(diff, noise) { 198 ann[i] = fmt.Sprintf("%+.02f%%", diff) 199 } 200 } 201 hh[i] = fmt.Sprintf("%v%v", v, d) 202 } else { 203 hh[i] = "NO DATA" 204 } 205 lastval = v 206 } 207 vals = append(vals, valf) 208 hints = append(hints, hh) 209 annotations = append(annotations, ann) 210 certainty = append(certainty, cert) 211 headers = append(headers, desc) 212 } 213 } 214 } 215 } 216 } 217 218 var commits []perfGraphCommit 219 if len(vals) != 0 && len(vals[0]) != 0 { 220 idx := 0 221 for i := range vals[0] { 222 com := commits2[i] 223 if com == nil || !com.NeedsBenchmarking { 224 continue 225 } 226 c := perfGraphCommit{Id: idx, Name: fmt.Sprintf("%v (%v)", com.Desc, com.Time.Format("Jan 2, 2006 1:04"))} 227 idx++ 228 for j := range vals { 229 c.Vals = append(c.Vals, perfGraphValue{float64(vals[j][i]), certainty[j][i], hints[j][i], annotations[j][i]}) 230 } 231 commits = append(commits, c) 232 } 233 } 234 235 data := &perfGraphData{d, cfg, headers, commits} 236 237 var buf bytes.Buffer 238 if err := perfGraphTemplate.Execute(&buf, data); err != nil { 239 logErr(w, r, err) 240 return 241 } 242 243 buf.WriteTo(w) 244 } 245 246 var perfGraphTemplate = template.Must( 247 template.New("perf_graph.html").ParseFiles("build/perf_graph.html"), 248 ) 249 250 type perfGraphData struct { 251 Dashboard *Dashboard 252 Config *uiPerfConfig 253 Headers []string 254 Commits []perfGraphCommit 255 } 256 257 type perfGraphCommit struct { 258 Id int 259 Name string 260 Vals []perfGraphValue 261 } 262 263 type perfGraphValue struct { 264 Val float64 265 Certainty bool 266 Hint string 267 Ann string 268 }