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

Side by Side Diff: fuzzer/go/frontend/syncer/fuzz_syncer.go

Issue 1695803002: Improve fuzz counts (Closed) Base URL: https://skia.googlesource.com/buildbot@dedup-first
Patch Set: Add docs Created 4 years, 10 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 | « fuzzer/go/data/report.go ('k') | fuzzer/go/fuzzer-fe/main.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 package syncer 1 package syncer
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 "sort" 5 "sort"
6 "strings" 6 "strings"
7 "sync" 7 "sync"
8 "time" 8 "time"
9 9
10 "github.com/skia-dev/glog" 10 "github.com/skia-dev/glog"
11 "go.skia.org/infra/fuzzer/go/common" 11 "go.skia.org/infra/fuzzer/go/common"
12 "go.skia.org/infra/fuzzer/go/config" 12 "go.skia.org/infra/fuzzer/go/config"
13 "go.skia.org/infra/fuzzer/go/frontend/gsloader" 13 "go.skia.org/infra/fuzzer/go/frontend/gsloader"
14 "go.skia.org/infra/go/gs" 14 "go.skia.org/infra/go/gs"
15 "go.skia.org/infra/go/util"
15 "google.golang.org/cloud/storage" 16 "google.golang.org/cloud/storage"
16 ) 17 )
17 18
18 // FuzzSyncer is a struct that will handle the syncing of bad/grey fuzzes. 19 // FuzzSyncer is a struct that will handle the syncing of bad/grey fuzzes.
19 // Once started, it will occasionally wake up and download any new fuzzes 20 // Once started, it will occasionally wake up and download any new fuzzes
20 // Clients should look at LastCount for the last count of fuzzes data. 21 // Clients should look at LastCount for the last count of fuzzes data.
21 type FuzzSyncer struct { 22 type FuzzSyncer struct {
22 countMutex sync.Mutex 23 countMutex sync.Mutex
23 storageClient *storage.Client 24 storageClient *storage.Client
24 gsLoader *gsloader.GSLoader 25 gsLoader *gsloader.GSLoader
25 » lastCount map[string]FuzzCount 26 » lastCount map[string]FuzzCount // maps category->FuzzCount
27 » fuzzNameCache map[string]util.StringSet // maps key->FuzzNames
26 } 28 }
27 29
28 // FuzzCount is a struct that holds the counts of fuzzes. 30 // FuzzCount is a struct that holds the counts of fuzzes.
29 type FuzzCount struct { 31 type FuzzCount struct {
30 TotalBad int `json:"totalBadCount"` 32 TotalBad int `json:"totalBadCount"`
31 TotalGrey int `json:"totalGreyCount"` 33 TotalGrey int `json:"totalGreyCount"`
32 // "This" means "newly introduced/fixed in this revision" 34 // "This" means "newly introduced/fixed in this revision"
33 » ThisBad int `json:"thisBadCount"` 35 » ThisBad int `json:"thisBadCount"`
34 » ThisGrey int `json:"thisGreyCount"` 36 » ThisRegression int `json:"thisRegressionCount"`
35 } 37 }
36 38
37 // NewFuzzSyncer creates a FuzzSyncer and returns it. 39 // NewFuzzSyncer creates a FuzzSyncer and returns it.
38 func New(s *storage.Client) *FuzzSyncer { 40 func New(s *storage.Client) *FuzzSyncer {
39 return &FuzzSyncer{ 41 return &FuzzSyncer{
40 storageClient: s, 42 storageClient: s,
41 lastCount: make(map[string]FuzzCount), 43 lastCount: make(map[string]FuzzCount),
44 fuzzNameCache: make(map[string]util.StringSet),
42 } 45 }
43 } 46 }
44 47
45 // SetGSLoader sets this objects GSLoader, allowing it to fetch the new fuzzes i t finds 48 // SetGSLoader sets this objects GSLoader, allowing it to fetch the new fuzzes i t finds
46 // and update the fuzzes displayed to users. 49 // and update the fuzzes displayed to users.
47 func (f *FuzzSyncer) SetGSLoader(g *gsloader.GSLoader) { 50 func (f *FuzzSyncer) SetGSLoader(g *gsloader.GSLoader) {
48 f.gsLoader = g 51 f.gsLoader = g
49 } 52 }
50 53
51 // Start updates the LastCount and starts a timer with a period of config.FrontE nd.FuzzSyncPeriod. 54 // Start updates the LastCount and starts a timer with a period of config.FrontE nd.FuzzSyncPeriod.
(...skipping 13 matching lines...) Expand all
65 func (f *FuzzSyncer) Refresh() { 68 func (f *FuzzSyncer) Refresh() {
66 glog.Info("Counting bad and grey fuzzes") 69 glog.Info("Counting bad and grey fuzzes")
67 currRevision := config.FrontEnd.SkiaVersion.Hash 70 currRevision := config.FrontEnd.SkiaVersion.Hash
68 prevRevision, err := f.getMostRecentOldRevision() 71 prevRevision, err := f.getMostRecentOldRevision()
69 if err != nil { 72 if err != nil {
70 glog.Infof("Problem getting most recent old version: %s", err) 73 glog.Infof("Problem getting most recent old version: %s", err)
71 return 74 return
72 } 75 }
73 f.countMutex.Lock() 76 f.countMutex.Lock()
74 defer f.countMutex.Unlock() 77 defer f.countMutex.Unlock()
75 » allCurrentNames := []string{} 78 » allBadFuzzes := util.NewStringSet()
76 79
77 for _, cat := range common.FUZZ_CATEGORIES { 80 for _, cat := range common.FUZZ_CATEGORIES {
78 lastCount := FuzzCount{} 81 lastCount := FuzzCount{}
79 currentBadNames, err := common.GetAllFuzzNamesInFolder(f.storage Client, fmt.Sprintf("%s/%s/bad", cat, currRevision))
80 if err != nil {
81 glog.Errorf("Problem getting total bad fuzz counts: %s", err)
82 } else {
83 lastCount.TotalBad = len(currentBadNames)
84 allCurrentNames = append(allCurrentNames, currentBadName s...)
85 }
86 82
87 » » if previousBadNames, err := common.GetAllFuzzNamesInFolder(f.sto rageClient, fmt.Sprintf("%s/%s/bad", cat, prevRevision)); err != nil { 83 » » // Previous fuzzes and current grey fuzzes can be drawn from the cache, if they aren't there.
88 » » » glog.Errorf("Problem getting this bad fuzz counts: %s", err) 84 » » previousGreyNames := f.getOrLookUpFuzzNames("grey", cat, prevRev ision)
89 » » } else { 85 » » previousBadNames := f.getOrLookUpFuzzNames("bad", cat, prevRevis ion)
90 » » » lastCount.ThisBad = lastCount.TotalBad - len(previousBad Names) 86 » » currentGreyNames := f.getOrLookUpFuzzNames("grey", cat, currRevi sion)
91 » » } 87 » » // always fetch current counts
88 » » currentBadNames := f.getFuzzNames("bad", cat, currRevision)
89 » » lastCount.TotalBad = len(currentBadNames)
90 » » lastCount.TotalGrey = len(currentGreyNames)
91 » » lastCount.ThisBad = len(currentBadNames.Complement(previousBadNa mes).Complement(previousGreyNames))
92 » » lastCount.ThisRegression = len(previousGreyNames.Intersect(curre ntBadNames))
93 » » allBadFuzzes = allBadFuzzes.Union(currentBadNames)
92 94
93 if currentGreyNames, err := common.GetAllFuzzNamesInFolder(f.sto rageClient, fmt.Sprintf("%s/%s/grey", cat, currRevision)); err != nil {
94 glog.Errorf("Problem getting total grey fuzz counts: %s" , err)
95 } else {
96 lastCount.TotalGrey = len(currentGreyNames)
97 }
98
99 if previousGreyNames, err := common.GetAllFuzzNamesInFolder(f.st orageClient, fmt.Sprintf("%s/%s/grey", cat, prevRevision)); err != nil {
100 glog.Errorf("Problem getting this grey fuzz counts: %s", err)
101 } else {
102 lastCount.ThisGrey = lastCount.TotalGrey - len(previousG reyNames)
103 }
104 f.lastCount[cat] = lastCount 95 f.lastCount[cat] = lastCount
105 } 96 }
106 97
107 » if err = f.updateLoadedBinaryFuzzes(allCurrentNames); err != nil { 98 » if err = f.updateLoadedBinaryFuzzes(allBadFuzzes.Keys()); err != nil {
108 glog.Errorf("Problem updating loaded binary fuzzes: %s", err) 99 glog.Errorf("Problem updating loaded binary fuzzes: %s", err)
109 } 100 }
110 } 101 }
111 102
112 // getMostRecentOldRevision finds the most recently updated revision used. 103 // getMostRecentOldRevision finds the most recently updated revision used.
113 // It searches the GS bucket under skia_version/old/ An error is returned if th ere is one. 104 // It searches the GS bucket under skia_version/old/ An error is returned if th ere is one.
114 func (f *FuzzSyncer) getMostRecentOldRevision() (string, error) { 105 func (f *FuzzSyncer) getMostRecentOldRevision() (string, error) {
115 var newestTime time.Time 106 var newestTime time.Time
116 newestHash := "" 107 newestHash := ""
117 findNewest := func(item *storage.ObjectAttrs) { 108 findNewest := func(item *storage.ObjectAttrs) {
118 glog.Infof("%s: %s", item.Name, item.Updated) 109 glog.Infof("%s: %s", item.Name, item.Updated)
119 if newestTime.Before(item.Updated) { 110 if newestTime.Before(item.Updated) {
120 newestTime = item.Updated 111 newestTime = item.Updated
121 newestHash = item.Name[strings.LastIndex(item.Name, "/") +1:] 112 newestHash = item.Name[strings.LastIndex(item.Name, "/") +1:]
122 } 113 }
123 } 114 }
124 if err := gs.AllFilesInDir(f.storageClient, config.GS.Bucket, "skia_vers ion/old/", findNewest); err != nil { 115 if err := gs.AllFilesInDir(f.storageClient, config.GS.Bucket, "skia_vers ion/old/", findNewest); err != nil {
125 return "", err 116 return "", err
126 } 117 }
127 glog.Infof("Most recent old version found to be %s", newestHash) 118 glog.Infof("Most recent old version found to be %s", newestHash)
128 return newestHash, nil 119 return newestHash, nil
129 } 120 }
130 121
122 // getOrLookUpFuzzNames first checks the cache for a StringSet of fuzz names lin ked to a given
123 // tuple of fuzzType (bad or grey), category, revision. If such a thing is not in the cache, it
124 // fetches it via getFuzzNames() and caches it for next time.
125 func (f *FuzzSyncer) getOrLookUpFuzzNames(fuzzType, category, revision string) u til.StringSet {
126 key := strings.Join([]string{fuzzType, category, revision}, "|")
127 if s, has := f.fuzzNameCache[key]; has {
128 return s
129 }
130 s := f.getFuzzNames(fuzzType, category, revision)
131 // cache it
132 f.fuzzNameCache[key] = s
133 return s
134 }
135
136 // getFuzzNames gets all the fuzz names belonging to a fuzzType, category, revis ion tuple from
137 // Google Storage. It tries two different ways to do this, first by reading a
138 // (bad|grey)_fuzz_names file, which exists in previous revisions. Second, it m anually counts
139 // all fuzzes in the given GCS folder.
140 func (f *FuzzSyncer) getFuzzNames(fuzzType, category, revision string) util.Stri ngSet {
141 // The file stored, if it exists, is a pipe seperated list.
142 if names, err := gs.FileContentsFromGS(f.storageClient, config.GS.Bucket , fmt.Sprintf("%s/%s/%s_fuzz_names.txt", category, revision, fuzzType)); err == nil {
143 return util.NewStringSet(strings.Split(string(names), "|"))
144 } else {
145 glog.Infof("Could not find cached names, downloading them the lo ng way, instead: %s", err)
146 }
147
148 if names, err := common.GetAllFuzzNamesInFolder(f.storageClient, fmt.Spr intf("%s/%s/%s", category, revision, fuzzType)); err != nil {
149 glog.Errorf("Problem fetching %s %s fuzzes at revision %s: %s", fuzzType, category, revision, err)
150 return nil
151 } else {
152 return util.NewStringSet(names)
153 }
154 }
155
131 // updateLoadedBinaryFuzzes uses gsLoader to download the fuzzes that are curren tly not 156 // updateLoadedBinaryFuzzes uses gsLoader to download the fuzzes that are curren tly not
132 // in the fuzz report tree / cache. 157 // in the fuzz report tree / cache.
133 func (f *FuzzSyncer) updateLoadedBinaryFuzzes(currentBadFuzzHashes []string) err or { 158 func (f *FuzzSyncer) updateLoadedBinaryFuzzes(currentBadFuzzHashes []string) err or {
134 if f.gsLoader == nil { 159 if f.gsLoader == nil {
135 glog.Info("Skipping update because the cache hasn't been set yet ") 160 glog.Info("Skipping update because the cache hasn't been set yet ")
136 return nil 161 return nil
137 } 162 }
138 prevBadFuzzNames, err := f.gsLoader.Cache.LoadFuzzNames(config.FrontEnd. SkiaVersion.Hash) 163 prevBadFuzzNames, err := f.gsLoader.Cache.LoadFuzzNames(config.FrontEnd. SkiaVersion.Hash)
139 if err != nil { 164 if err != nil {
140 return fmt.Errorf("Could not load previous fuzz hashes from cach e at revision %s: %s", config.FrontEnd.SkiaVersion.Hash, err) 165 return fmt.Errorf("Could not load previous fuzz hashes from cach e at revision %s: %s", config.FrontEnd.SkiaVersion.Hash, err)
(...skipping 12 matching lines...) Expand all
153 glog.Infof("%d newly found fuzzes from Google Storage. Going to load th em.", len(newBinaryFuzzNames)) 178 glog.Infof("%d newly found fuzzes from Google Storage. Going to load th em.", len(newBinaryFuzzNames))
154 if len(newBinaryFuzzNames) > 0 { 179 if len(newBinaryFuzzNames) > 0 {
155 return f.gsLoader.LoadFuzzesFromGoogleStorage(newBinaryFuzzNames ) 180 return f.gsLoader.LoadFuzzesFromGoogleStorage(newBinaryFuzzNames )
156 } 181 }
157 return nil 182 return nil
158 } 183 }
159 184
160 func (f *FuzzSyncer) LastCount(category string) FuzzCount { 185 func (f *FuzzSyncer) LastCount(category string) FuzzCount {
161 return f.lastCount[category] 186 return f.lastCount[category]
162 } 187 }
OLDNEW
« no previous file with comments | « fuzzer/go/data/report.go ('k') | fuzzer/go/fuzzer-fe/main.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698