133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# Copyright 2012 the V8 project authors. All rights reserved. 233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# Redistribution and use in source and binary forms, with or without 333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# modification, are permitted provided that the following conditions are 433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# met: 533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# 633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# * Redistributions of source code must retain the above copyright 733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# notice, this list of conditions and the following disclaimer. 833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# * Redistributions in binary form must reproduce the above 933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# copyright notice, this list of conditions and the following 1033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# disclaimer in the documentation and/or other materials provided 1133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# with the distribution. 1233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# * Neither the name of Google Inc. nor the names of its 1333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# contributors may be used to endorse or promote products derived 1433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# from this software without specific prior written permission. 1533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# 1633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 2833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 2933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport os 3033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport shelve 3133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport threading 3233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 3333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 3433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass PerfDataEntry(object): 3533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def __init__(self): 3633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.avg = 0.0 3733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.count = 0 3833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 3933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def AddResult(self, result): 4033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org kLearnRateLimiter = 99 # Greater value means slower learning. 4133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org # We use an approximation of the average of the last 100 results here: 4233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org # The existing average is weighted with kLearnRateLimiter (or less 4333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org # if there are fewer data points). 4433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org effective_count = min(self.count, kLearnRateLimiter) 4533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.avg = self.avg * effective_count + result 4633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.count = effective_count + 1 4733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.avg /= self.count 4833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 4933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 5033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass PerfDataStore(object): 5133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def __init__(self, datadir, arch, mode): 5233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org filename = os.path.join(datadir, "%s.%s.perfdata" % (arch, mode)) 5333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.database = shelve.open(filename, protocol=2) 5433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.closed = False 5533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.lock = threading.Lock() 5633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 5733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def __del__(self): 5833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.close() 5933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 6033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def close(self): 6133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if self.closed: return 6233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.database.close() 6333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.closed = True 6433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 6533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def GetKey(self, test): 6633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org """Computes the key used to access data for the given testcase.""" 6733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org flags = "".join(test.flags) 6833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return str("%s.%s.%s" % (test.suitename(), test.path, flags)) 6933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 7033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def FetchPerfData(self, test): 7133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org """Returns the observed duration for |test| as read from the store.""" 7233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org key = self.GetKey(test) 7333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if key in self.database: 7433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return self.database[key].avg 7533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return None 7633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 7733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def UpdatePerfData(self, test): 7833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org """Updates the persisted value in the store with test.duration.""" 7933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org testkey = self.GetKey(test) 8033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.RawUpdatePerfData(testkey, test.duration) 8133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 8233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def RawUpdatePerfData(self, testkey, duration): 8333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org with self.lock: 8433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if testkey in self.database: 8533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org entry = self.database[testkey] 8633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org else: 8733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org entry = PerfDataEntry() 8833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org entry.AddResult(duration) 8933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.database[testkey] = entry 9033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 9133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 9233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass PerfDataManager(object): 9333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def __init__(self, datadir): 9433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.datadir = os.path.abspath(datadir) 9533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not os.path.exists(self.datadir): 9633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org os.makedirs(self.datadir) 9733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.stores = {} # Keyed by arch, then mode. 9833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.closed = False 9933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.lock = threading.Lock() 10033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 10133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def __del__(self): 10233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.close() 10333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 10433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def close(self): 10533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if self.closed: return 10633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org for arch in self.stores: 10733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org modes = self.stores[arch] 10833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org for mode in modes: 10933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org store = modes[mode] 11033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org store.close() 11133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.closed = True 11233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 11333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def GetStore(self, arch, mode): 11433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org with self.lock: 11533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not arch in self.stores: 11633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.stores[arch] = {} 11733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org modes = self.stores[arch] 11833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not mode in modes: 11933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org modes[mode] = PerfDataStore(self.datadir, arch, mode) 12033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return modes[mode] 121