Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Side by Side Diff: go/src/infra/tools/swarming-transition/cmd/swarmbucketcheck/main.go

Issue 2109953002: swarmbucketcheck: compare time (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: swarmbucketcheck: compare time Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package main 5 package main
6 6
7 import ( 7 import (
8 "flag" 8 "flag"
9 "fmt" 9 "fmt"
10 "net/http" 10 "net/http"
11 "os" 11 "os"
12 "sort"
12 "strings" 13 "strings"
13 "time" 14 "time"
14 15
15 "github.com/luci/luci-go/common/api/buildbucket/buildbucket/v1" 16 "github.com/luci/luci-go/common/api/buildbucket/buildbucket/v1"
16 ) 17 )
17 18
18 var since = flag.Int64("since", 0, "analyze builds since this timestamp. Default s to 10 days ago.") 19 var since = flag.Int64("since", 0, "analyze builds since this timestamp. Default s to 10 days ago.")
19 var bucket = flag.String("bucket", "", `buildbucket bucket name, e.g. "master.tr yserver.infra"`) 20 var bucket = flag.String("bucket", "", `buildbucket bucket name, e.g. "master.tr yserver.infra"`)
20 var builders = flag.String("builder", "", `comma-separated list of builder names without swarming suffix, e.g. "Infra Presubmit"`) 21 var builders = flag.String("builder", "", `comma-separated list of builder names without swarming suffix, e.g. "Infra Presubmit"`)
21 22
(...skipping 16 matching lines...) Expand all
38 for { 39 for {
39 res, err := req.Do() 40 res, err := req.Do()
40 if err != nil { 41 if err != nil {
41 return result, err 42 return result, err
42 } 43 }
43 if res.Error != nil { 44 if res.Error != nil {
44 return result, fmt.Errorf(res.Error.Message) 45 return result, fmt.Errorf(res.Error.Message)
45 } 46 }
46 47
47 for _, b := range res.Builds { 48 for _, b := range res.Builds {
48 » » » createdAt := time.Unix(b.CreatedTs/1000000, 0) 49 » » » if parseTimestamp(b.CreatedTs).Before(startingFrom) {
49 » » » if createdAt.Before(startingFrom) {
50 return result, nil 50 return result, nil
51 } 51 }
52 result = append(result, b) 52 result = append(result, b)
53 } 53 }
54 54
55 if len(res.Builds) == 0 || res.NextCursor == "" { 55 if len(res.Builds) == 0 || res.NextCursor == "" {
56 break 56 break
57 } 57 }
58 req.StartCursor(res.NextCursor) 58 req.StartCursor(res.NextCursor)
59 } 59 }
(...skipping 22 matching lines...) Expand all
82 } 82 }
83 83
84 set.builds = append(set.builds, b) 84 set.builds = append(set.builds, b)
85 if set.bestResult == "" || b.Result == "SUCCESS" { 85 if set.bestResult == "" || b.Result == "SUCCESS" {
86 set.bestResult = b.Result 86 set.bestResult = b.Result
87 } 87 }
88 } 88 }
89 return results 89 return results
90 } 90 }
91 91
92 // medianTime returns median completed_time - created_time of successful builds.
93 func medianTime(builds []*buildbucket.ApiBuildMessage) time.Duration {
94 if len(builds) == 0 {
95 return 0
96 }
97 durations := make(durationSlice, 0, len(builds))
98 for _, b := range builds {
99 if b.Result != "SUCCESS" {
100 continue
101 }
102 created := parseTimestamp(b.CreatedTs)
103 completed := parseTimestamp(b.CompletedTs)
104 durations = append(durations, completed.Sub(created))
105 }
106 sort.Sort(durations)
107 return durations[len(durations)/2]
108 }
109
92 func run() error { 110 func run() error {
93 flag.Parse() 111 flag.Parse()
94 if *bucket == "" { 112 if *bucket == "" {
95 return fmt.Errorf("bucket is not specified") 113 return fmt.Errorf("bucket is not specified")
96 } 114 }
97 if *builders == "" { 115 if *builders == "" {
98 return fmt.Errorf("builders are not specified") 116 return fmt.Errorf("builders are not specified")
99 } 117 }
100 if len(flag.Args()) > 0 { 118 if len(flag.Args()) > 0 {
101 return fmt.Errorf("unexpected arguments: %s", flag.Args()) 119 return fmt.Errorf("unexpected arguments: %s", flag.Args())
(...skipping 12 matching lines...) Expand all
114 for i, builder := range strings.Split(*builders, ",") { 132 for i, builder := range strings.Split(*builders, ",") {
115 builder = strings.TrimSpace(builder) 133 builder = strings.TrimSpace(builder)
116 if builder == "" { 134 if builder == "" {
117 continue 135 continue
118 } 136 }
119 137
120 if i > 0 { 138 if i > 0 {
121 fmt.Println() 139 fmt.Println()
122 } 140 }
123 fmt.Printf("builder %q\n", builder) 141 fmt.Printf("builder %q\n", builder)
124 » » fmt.Printf("searching for all builds since timestamp %d till %d. ..\n", 142 » » if err := compareBuilder(builder, startingFrom); err != nil {
125 » » » startingFrom.Unix(), time.Now().Unix()) 143 » » » return err
126 » » // We will actually fetch builds after after time.Now too, but i t is fine.
127 » » swarmingBuilds, err := fetchBuilds(*bucket, builder+swarmingSuff ix, startingFrom)
128 » » if err != nil {
129 » » » return fmt.Errorf("could not fetch builds: %s", err)
130 } 144 }
131 if len(swarmingBuilds) == 0 {
132 fmt.Printf("no swarming builds for builder %q\n", builde r)
133 continue
134 }
135 buildbotBuilds, err := fetchBuilds(*bucket, builder, startingFro m)
136 if err != nil {
137 return fmt.Errorf("could not fetch builds: %s", err)
138 }
139
140 swarmingBuildSets := groupBuilds(swarmingBuilds)
141 buildbotBuildSets := groupBuilds(buildbotBuilds)
142
143 consistentN := 0
144 inconsistentN := 0
145 for setName, swarmingSet := range swarmingBuildSets {
146 buildbotSet := buildbotBuildSets[setName]
147 if buildbotSet == nil {
148 fmt.Printf("no buildbot builds for buildset %s\n ", setName)
149 continue
150 }
151 if buildbotSet.bestResult == swarmingSet.bestResult {
152 consistentN++
153 continue
154 }
155 inconsistentN++
156
157 fmt.Printf("%s is inconsistent\n", setName)
158 for _, b := range swarmingSet.builds {
159 fmt.Printf(" %s %s\n", b.Result, b.Url)
160 }
161 for _, b := range buildbotSet.builds {
162 fmt.Printf(" %s %s\n", b.Result, b.Url)
163 }
164 }
165
166 fmt.Printf("%0.2f%% consistent build sets, %d buildbot builds, % d swarming builds\n",
167 100*float64(consistentN)/float64(consistentN+inconsisten tN), len(buildbotBuilds), len(swarmingBuilds))
168 } 145 }
169 return nil 146 return nil
170 } 147 }
171 148
149 func compareBuilder(builder string, startingFrom time.Time) error {
150 fmt.Printf("searching for all builds since timestamp %d till %d...\n",
151 startingFrom.Unix(), time.Now().Unix())
152 // We will actually fetch builds after after time.Now too, but it is fin e.
153 swarmingBuilds, err := fetchBuilds(*bucket, builder+swarmingSuffix, star tingFrom)
154 if err != nil {
155 return fmt.Errorf("could not fetch builds: %s", err)
156 }
157 if len(swarmingBuilds) == 0 {
158 fmt.Printf("no swarming builds for builder %q\n", builder)
159 return nil
160 }
161 buildbotBuilds, err := fetchBuilds(*bucket, builder, startingFrom)
162 if err != nil {
163 return fmt.Errorf("could not fetch builds: %s", err)
164 }
165 if len(buildbotBuilds) == 0 {
166 fmt.Printf("no buildbot builds for builder %q\n", builder)
167 return nil
168 }
169
170 swarmingBuildSets := groupBuilds(swarmingBuilds)
171 buildbotBuildSets := groupBuilds(buildbotBuilds)
172
173 consistentN := 0
174 inconsistentN := 0
175 for setName, swarmingSet := range swarmingBuildSets {
176 buildbotSet := buildbotBuildSets[setName]
177 if buildbotSet == nil {
178 fmt.Printf("no buildbot builds for buildset %s\n", setNa me)
179 continue
180 }
181 if buildbotSet.bestResult == swarmingSet.bestResult {
182 consistentN++
183 continue
184 }
185 inconsistentN++
186
187 fmt.Printf("%s is inconsistent\n", setName)
188 for _, b := range swarmingSet.builds {
189 fmt.Printf(" %s %s\n", b.Result, b.Url)
190 }
191 for _, b := range buildbotSet.builds {
192 fmt.Printf(" %s %s\n", b.Result, b.Url)
193 }
194 }
195
196 fmt.Printf("%0.2f%% consistent build sets, %d buildbot builds, %d swarmi ng builds\n",
197 100*float64(consistentN)/float64(consistentN+inconsistentN), len (buildbotBuilds), len(swarmingBuilds))
198
199 swarmingTime := medianTime(swarmingBuilds)
200 buildbotTime := medianTime(buildbotBuilds)
201 factor := float64(buildbotTime) / float64(swarmingTime)
202 if factor >= 1 {
203 fmt.Printf("swarming is %.1fx faster\n", factor)
204 } else {
205 fmt.Printf("swarming is %.1fx slower\n", 1/factor)
206 }
207 fmt.Printf("median times: buildbot %s, swarming %s\n", buildbotTime, swa rmingTime)
208
209 return nil
210 }
211
172 func main() { 212 func main() {
173 if err := run(); err != nil { 213 if err := run(); err != nil {
174 fmt.Fprintln(os.Stderr, err) 214 fmt.Fprintln(os.Stderr, err)
175 os.Exit(1) 215 os.Exit(1)
176 } 216 }
177 } 217 }
178 218
179 func parseTags(tags []string) map[string]string { 219 func parseTags(tags []string) map[string]string {
180 result := make(map[string]string, len(tags)) 220 result := make(map[string]string, len(tags))
181 for _, t := range tags { 221 for _, t := range tags {
182 parts := strings.SplitN(t, ":", 2) 222 parts := strings.SplitN(t, ":", 2)
183 if len(parts) == 2 { 223 if len(parts) == 2 {
184 result[parts[0]] = parts[1] 224 result[parts[0]] = parts[1]
185 } 225 }
186 } 226 }
187 return result 227 return result
188 } 228 }
229
230 func parseTimestamp(ts int64) time.Time {
231 if ts == 0 {
232 return time.Time{}
233 }
234 return time.Unix(ts/1000000, 0)
235 }
236
237 type durationSlice []time.Duration
238
239 func (a durationSlice) Len() int { return len(a) }
240 func (a durationSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
241 func (a durationSlice) Less(i, j int) bool { return a[i] < a[j] }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698