github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/dashboard/app/build/perf_detail.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 "strconv" 16 "strings" 17 18 "appengine" 19 "appengine/datastore" 20 ) 21 22 func init() { 23 handleFunc("/perfdetail", perfDetailUIHandler) 24 } 25 26 func perfDetailUIHandler(w http.ResponseWriter, r *http.Request) { 27 d := dashboardForRequest(r) 28 c := d.Context(appengine.NewContext(r)) 29 pc, err := GetPerfConfig(c, r) 30 if err != nil { 31 logErr(w, r, err) 32 return 33 } 34 35 kind := r.FormValue("kind") 36 builder := r.FormValue("builder") 37 benchmark := r.FormValue("benchmark") 38 if kind == "" { 39 kind = "benchmark" 40 } 41 if kind != "benchmark" && kind != "builder" { 42 logErr(w, r, fmt.Errorf("unknown kind %s", kind)) 43 return 44 } 45 46 // Fetch the new commit. 47 com1 := new(Commit) 48 com1.Hash = r.FormValue("commit") 49 if hash, ok := knownTags[com1.Hash]; ok { 50 com1.Hash = hash 51 } 52 if err := datastore.Get(c, com1.Key(c), com1); err != nil { 53 logErr(w, r, fmt.Errorf("failed to fetch commit %s: %v", com1.Hash, err)) 54 return 55 } 56 // Fetch the associated perf result. 57 ress1 := &PerfResult{CommitHash: com1.Hash} 58 if err := datastore.Get(c, ress1.Key(c), ress1); err != nil { 59 logErr(w, r, fmt.Errorf("failed to fetch perf result %s: %v", com1.Hash, err)) 60 return 61 } 62 63 // Fetch the old commit. 64 var ress0 *PerfResult 65 com0 := new(Commit) 66 com0.Hash = r.FormValue("commit0") 67 if hash, ok := knownTags[com0.Hash]; ok { 68 com0.Hash = hash 69 } 70 if com0.Hash != "" { 71 // Have an exact commit hash, fetch directly. 72 if err := datastore.Get(c, com0.Key(c), com0); err != nil { 73 logErr(w, r, fmt.Errorf("failed to fetch commit %s: %v", com0.Hash, err)) 74 return 75 } 76 ress0 = &PerfResult{CommitHash: com0.Hash} 77 if err := datastore.Get(c, ress0.Key(c), ress0); err != nil { 78 logErr(w, r, fmt.Errorf("failed to fetch perf result for %s: %v", com0.Hash, err)) 79 return 80 } 81 } else { 82 // Don't have the commit hash, find the previous commit to compare. 83 rc := MakePerfResultCache(c, com1, false) 84 ress0, err = rc.NextForComparison(com1.Num, "") 85 if err != nil { 86 logErr(w, r, err) 87 return 88 } 89 if ress0 == nil { 90 logErr(w, r, fmt.Errorf("no previous commit with results")) 91 return 92 } 93 // Now that we know the right result, fetch the commit. 94 com0.Hash = ress0.CommitHash 95 if err := datastore.Get(c, com0.Key(c), com0); err != nil { 96 logErr(w, r, fmt.Errorf("failed to fetch commit %s: %v", com0.Hash, err)) 97 return 98 } 99 } 100 101 res0 := ress0.ParseData() 102 res1 := ress1.ParseData() 103 var benchmarks []*uiPerfDetailBenchmark 104 var list []string 105 if kind == "builder" { 106 list = pc.BenchmarksForBuilder(builder) 107 } else { 108 list = pc.BuildersForBenchmark(benchmark) 109 } 110 for _, other := range list { 111 if kind == "builder" { 112 benchmark = other 113 } else { 114 builder = other 115 } 116 var procs []*uiPerfDetailProcs 117 allProcs := pc.ProcList(builder) 118 for _, p := range allProcs { 119 BenchProcs := fmt.Sprintf("%v-%v", benchmark, p) 120 if res0[builder] == nil || res0[builder][BenchProcs] == nil { 121 continue 122 } 123 pp := &uiPerfDetailProcs{Procs: p} 124 for metric, val := range res0[builder][BenchProcs].Metrics { 125 var pm uiPerfDetailMetric 126 pm.Name = metric 127 pm.Val0 = fmt.Sprintf("%v", val) 128 val1 := uint64(0) 129 if res1[builder] != nil && res1[builder][BenchProcs] != nil { 130 val1 = res1[builder][BenchProcs].Metrics[metric] 131 } 132 pm.Val1 = fmt.Sprintf("%v", val1) 133 v0 := val 134 v1 := val1 135 valf := perfDiff(v0, v1) 136 pm.Delta = fmt.Sprintf("%+.2f%%", valf) 137 pm.Style = perfChangeStyle(pc, valf, builder, BenchProcs, pm.Name) 138 pp.Metrics = append(pp.Metrics, pm) 139 } 140 sort.Sort(pp.Metrics) 141 for artifact, hash := range res0[builder][BenchProcs].Artifacts { 142 var pm uiPerfDetailMetric 143 pm.Val0 = fmt.Sprintf("%v", artifact) 144 pm.Link0 = fmt.Sprintf("log/%v", hash) 145 pm.Val1 = fmt.Sprintf("%v", artifact) 146 if res1[builder] != nil && res1[builder][BenchProcs] != nil && res1[builder][BenchProcs].Artifacts[artifact] != "" { 147 pm.Link1 = fmt.Sprintf("log/%v", res1[builder][BenchProcs].Artifacts[artifact]) 148 } 149 pp.Metrics = append(pp.Metrics, pm) 150 } 151 procs = append(procs, pp) 152 } 153 benchmarks = append(benchmarks, &uiPerfDetailBenchmark{other, procs}) 154 } 155 156 cfg := new(uiPerfConfig) 157 for _, v := range pc.BuildersForBenchmark("") { 158 cfg.Builders = append(cfg.Builders, uiPerfConfigElem{v, v == builder}) 159 } 160 for _, v := range pc.BenchmarksForBuilder("") { 161 cfg.Benchmarks = append(cfg.Benchmarks, uiPerfConfigElem{v, v == benchmark}) 162 } 163 164 data := &uiPerfDetailTemplateData{d, cfg, kind == "builder", com0, com1, benchmarks} 165 166 var buf bytes.Buffer 167 if err := uiPerfDetailTemplate.Execute(&buf, data); err != nil { 168 logErr(w, r, err) 169 return 170 } 171 172 buf.WriteTo(w) 173 } 174 175 func perfResultSplit(s string) (builder string, benchmark string, procs int) { 176 s1 := strings.Split(s, "|") 177 s2 := strings.Split(s1[1], "-") 178 procs, _ = strconv.Atoi(s2[1]) 179 return s1[0], s2[0], procs 180 } 181 182 type uiPerfDetailTemplateData struct { 183 Dashboard *Dashboard 184 Config *uiPerfConfig 185 KindBuilder bool 186 Commit0 *Commit 187 Commit1 *Commit 188 Benchmarks []*uiPerfDetailBenchmark 189 } 190 191 type uiPerfDetailBenchmark struct { 192 Name string 193 Procs []*uiPerfDetailProcs 194 } 195 196 type uiPerfDetailProcs struct { 197 Procs int 198 Metrics uiPerfDetailMetrics 199 } 200 201 type uiPerfDetailMetric struct { 202 Name string 203 Val0 string 204 Val1 string 205 Link0 string 206 Link1 string 207 Delta string 208 Style string 209 } 210 211 type uiPerfDetailMetrics []uiPerfDetailMetric 212 213 func (l uiPerfDetailMetrics) Len() int { return len(l) } 214 func (l uiPerfDetailMetrics) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 215 func (l uiPerfDetailMetrics) Less(i, j int) bool { return l[i].Name < l[j].Name } 216 217 var uiPerfDetailTemplate = template.Must( 218 template.New("perf_detail.html").Funcs(tmplFuncs).ParseFiles("build/perf_detail.html"), 219 )