| Index: third_party/buildbot_8_4p1/README.chromium
|
| ===================================================================
|
| --- third_party/buildbot_8_4p1/README.chromium (revision 127129)
|
| +++ third_party/buildbot_8_4p1/README.chromium (working copy)
|
| @@ -1199,3 +1199,149 @@
|
| kwargs['logfiles'] = self.logfiles
|
|
|
| # check for the usePTY flag
|
| +
|
| +For performance, switch to the good LRU cache implementation.
|
| +
|
| +Index: buildbot/status/builder.py
|
| +===================================================================
|
| +--- buildbot/status/builder.py (revision 127129)
|
| ++++ buildbot/status/builder.py (working copy)
|
| +@@ -86,8 +86,10 @@
|
| + self.currentBuilds = []
|
| + self.nextBuild = None
|
| + self.watchers = []
|
| +- self.buildCache = weakref.WeakValueDictionary()
|
| +- self.buildCache_LRU = []
|
| ++ #self.buildCache = weakref.WeakValueDictionary()
|
| ++ #self.buildCache_LRU = []
|
| ++ self.buildCache = util.lru.AsyncLRUCache(self.cacheMiss,
|
| ++ self.buildCacheSize)
|
| + self.logCompressionLimit = False # default to no compression for tests
|
| + self.logCompressionMethod = "bz2"
|
| + self.logMaxSize = None # No default limit
|
| +@@ -103,7 +105,7 @@
|
| + d = styles.Versioned.__getstate__(self)
|
| + d['watchers'] = []
|
| + del d['buildCache']
|
| +- del d['buildCache_LRU']
|
| ++ #del d['buildCache_LRU']
|
| + for b in self.currentBuilds:
|
| + b.saveYourself()
|
| + # TODO: push a 'hey, build was interrupted' event
|
| +@@ -119,8 +121,10 @@
|
| + # when loading, re-initialize the transient stuff. Remember that
|
| + # upgradeToVersion1 and such will be called after this finishes.
|
| + styles.Versioned.__setstate__(self, d)
|
| +- self.buildCache = weakref.WeakValueDictionary()
|
| +- self.buildCache_LRU = []
|
| ++ #self.buildCache = weakref.WeakValueDictionary()
|
| ++ #self.buildCache_LRU = []
|
| ++ self.buildCache = util.lru.AsyncLRUCache(self.cacheMiss,
|
| ++ self.buildCacheSize)
|
| + self.currentBuilds = []
|
| + self.watchers = []
|
| + self.slavenames = []
|
| +@@ -132,6 +136,7 @@
|
| + # gets pickled and unpickled.
|
| + if buildmaster.buildCacheSize is not None:
|
| + self.buildCacheSize = buildmaster.buildCacheSize
|
| ++ self.buildCache.set_max_size(buildmaster.buildCacheSize)
|
| +
|
| + def upgradeToVersion1(self):
|
| + if hasattr(self, 'slavename'):
|
| +@@ -186,33 +191,24 @@
|
| + except:
|
| + log.msg("unable to save builder %s" % self.name)
|
| + log.err()
|
| +-
|
| +
|
| ++
|
| + # build cache management
|
| +
|
| + def makeBuildFilename(self, number):
|
| + return os.path.join(self.basedir, "%d" % number)
|
| +
|
| +- def touchBuildCache(self, build):
|
| +- self.buildCache[build.number] = build
|
| +- if build in self.buildCache_LRU:
|
| +- self.buildCache_LRU.remove(build)
|
| +- self.buildCache_LRU = self.buildCache_LRU[-(self.buildCacheSize-1):] + [ build ]
|
| +- return build
|
| ++# def touchBuildCache(self, build):
|
| ++# self.buildCache[build.number] = build
|
| ++# if build in self.buildCache_LRU:
|
| ++# self.buildCache_LRU.remove(build)
|
| ++# self.buildCache_LRU = self.buildCache_LRU[-(self.buildCacheSize-1):] + [ build ]
|
| ++# return build
|
| +
|
| + def getBuildByNumber(self, number):
|
| +- # first look in currentBuilds
|
| +- for b in self.currentBuilds:
|
| +- if b.number == number:
|
| +- return self.touchBuildCache(b)
|
| ++ return self.buildCache.get(number)
|
| +
|
| +- # then in the buildCache
|
| +- if number in self.buildCache:
|
| +- metrics.MetricCountEvent.log("buildCache.hits", 1)
|
| +- return self.touchBuildCache(self.buildCache[number])
|
| +- metrics.MetricCountEvent.log("buildCache.misses", 1)
|
| +-
|
| +- # then fall back to loading it from disk
|
| ++ def loadBuildFromFile(self, number):
|
| + filename = self.makeBuildFilename(number)
|
| + try:
|
| + log.msg("Loading builder %s's build %d from on-disk pickle"
|
| +@@ -235,12 +231,23 @@
|
| + build.upgradeLogfiles()
|
| + # check that logfiles exist
|
| + build.checkLogfiles()
|
| +- return self.touchBuildCache(build)
|
| ++ #return self.touchBuildCache(build)
|
| ++ return build
|
| + except IOError:
|
| + raise IndexError("no such build %d" % number)
|
| + except EOFError:
|
| + raise IndexError("corrupted build pickle %d" % number)
|
| +
|
| ++ def cacheMiss(self, number):
|
| ++ # first look in currentBuilds
|
| ++ for b in self.currentBuilds:
|
| ++ if b.number == number:
|
| ++ #return self.touchBuildCache(b)
|
| ++ return defer.succeed(b)
|
| ++
|
| ++ # then fall back to loading it from disk
|
| ++ return threads.deferToThread(self.loadBuildFromFile, number)
|
| ++
|
| + def prune(self, events_only=False):
|
| + # begin by pruning our own events
|
| + self.events = self.events[-self.eventHorizon:]
|
| +@@ -287,7 +294,7 @@
|
| + is_logfile = True
|
| +
|
| + if num is None: continue
|
| +- if num in self.buildCache: continue
|
| ++ if num in self.buildCache.cache: continue
|
| +
|
| + if (is_logfile and num < earliest_log) or num < earliest_build:
|
| + pathname = os.path.join(self.basedir, filename)
|
| +@@ -510,7 +517,8 @@
|
| + assert s.number == self.nextBuildNumber - 1
|
| + assert s not in self.currentBuilds
|
| + self.currentBuilds.append(s)
|
| +- self.touchBuildCache(s)
|
| ++ #self.touchBuildCache(s)
|
| ++ self.buildCache.put(s.number, s)
|
| +
|
| + # now that the BuildStatus is prepared to answer queries, we can
|
| + # announce the new build to all our watchers
|
| +@@ -620,7 +628,7 @@
|
| + # Collect build numbers.
|
| + # Important: Only grab the *cached* builds numbers to reduce I/O.
|
| + current_builds = [b.getNumber() for b in self.currentBuilds]
|
| +- cached_builds = list(set(self.buildCache.keys() + current_builds))
|
| ++ cached_builds = list(set(self.buildCache.cache.keys() + current_builds))
|
| + cached_builds.sort()
|
| + result['cachedBuilds'] = cached_builds
|
| + result['currentBuilds'] = current_builds
|
|
|