File: result.py

package info (click to toggle)
pypy3 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 111,848 kB
  • sloc: python: 1,291,746; ansic: 74,281; asm: 5,187; cpp: 3,017; sh: 2,533; makefile: 544; xml: 243; lisp: 45; csh: 21; awk: 4
file content (238 lines) | stat: -rw-r--r-- 8,140 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

import py

class PerfResult:
    """Holds information about a benchmark run of a particular test run."""
    
    def __init__(self, date=0.0, test_id="", revision=0.0, 
                 revision_id="NONE", timestamp=0.0,
                 revision_date=0.0, elapsed_time=-1, 
                 committer="", message="", nick=""): 
        self.__dict__.update(locals())
        del self.self

        
class PerfResultCollection(object):
    """Holds information about several PerfResult objects. The
    objects should have the same test_id and revision_id"""
    
    def __init__(self, results=None):
        if results is None:
            self.results = []
        else:
            self.results = results[:]
        #self.check()

    def __repr__(self):
        self.check()
        if not self.results:
            return "<PerfResultCollection EMPTY>"
        sample = self.results[0]
        return "<PerfResultCollection test_id=%s, revno=%s>" %(
               sample.test_id, sample.revision)
    
    @property   
    def min_elapsed(self):
        return self.getfastest().elapsed_time 

    def getfastest(self):
        x = None
        for res in self.results:
            if x is None or res.elapsed_time < x.elapsed_time: 
                x = res
        return x

    @property
    def test_id(self):
        # check for empty results?
        return self.results[0].test_id

    @property
    def revision_id(self):
        # check for empty results?
        return self.results[0].revision_id

    @property
    def revision(self):
        # check for empty results?
        return self.results[0].revision
           
    def check(self):
        for s1, s2 in zip(self.results, self.results[1:]):
            assert s1.revision_id == s2.revision_id 
            assert s1.test_id == s2.test_id
            assert s1.revision == s2.revision
            assert s1.date != s2.date
            
    def append(self, sample):
        self.results.append(sample)
        self.check()

    def extend(self, results):
        self.results.extend(results)
        self.check() 
        
    def __len__(self):
        return len(self.results)


class PerfResultDelta:
    """represents the difference of two PerfResultCollections"""

    def __init__(self, _from, _to=None): 
        if _from is None:
            _from = _to
        if _to is None:
            _to = _from
        if isinstance(_from, list):
            _from = PerfResultCollection(_from)
        if isinstance(_to, list):
            _to = PerfResultCollection(_to)
        assert isinstance(_from, PerfResultCollection)
        assert isinstance(_to, PerfResultCollection)
        assert _from.test_id == _to.test_id, (_from.test_id, _to.test_id)
        self._from = _from
        self._to = _to
        self.test_id = self._to.test_id
        self.delta = self._to.min_elapsed - self._from.min_elapsed 

        # percentage
        m1 = self._from.min_elapsed 
        m2 = self._to.min_elapsed 
        if m1 == 0: 
            self.percent = 0.0
        else:
            self.percent = float(m2-m1) / float(m1)

class PerfTable:
    """parses performance history data files and yields PerfResult objects
    through the get_results method.

    if an branch is given, it is used to get more information for each
    revision we have data from.
    """
    branch = None
    
    def __init__(self, iterlines = []):
        """:param iterline: lines of performance history data,
        e.g., history_file.realdlines()
        """
        self._revision_cache = {}
        self.results = list(self.parse(iterlines))
        
    def parse(self, iterlines):
        """parse lines like
        --date 1152625530.0 hacker@canonical.com-20..6dc
          1906ms bzrlib....one_add_kernel_like_tree
        """
        date = None
        revision_id = None
        for line in iterlines:
            line = line.strip()
            if not line:
                continue
            if line.startswith('--date'):
                _, date, revision_id = line.split(None, 2)
                date = float(date)
                continue
            perfresult = PerfResult(date=date, revision_id=revision_id)
            elapsed_time, test_id = line.split(None, 1)
            perfresult.elapsed_time = int(elapsed_time[:-2])
            perfresult.test_id = test_id.strip()
            yield self.annotate(perfresult)
        
    def add_lines(self, lines):
        """add lines of performance history data """
        
        self.results += list(self.parse(lines))

    def get_time_for_revision_id(self, revision_id):
        """return the data of the revision or 0"""
        if revision_id in self._revision_cache:
            return self._revision_cache[revision_id][1].timestamp
        return 0
        
    def get_time(self, revision_id):
        """return revision date or the date of recording the
        performance history data"""
        
        t = self.get_time_for_revision_id(revision_id)
        if t: 
            return t
        result = list(self.get_results(revision_ids=[revision_id],
                                       sorted_by_rev_date=False))[0]
        return result.date
   
    count = py.std.itertools.count() 
    def annotate(self, result):
        """Try to put extra information for each revision on the
        PerfResult objects. These information are retrieved from a
        branch object.
        """
        #if self.branch is None:
        #    return result
        class Branch:
            revision_id = result.revision_id  
            nick = "fake"
        
        self.branch = Branch()
        result.revision = self.count.next()
        result.revision_date = "01/01/2007"
        result.message = "fake log message"
        result.timestamp = 1231231.0
        return result
        

        revision_id = result.revision_id
        if revision_id in self._revision_cache:
            revision, rev, nick = self._revision_cache[revision_id]
        else:
            revision =  self.branch.revision_id_to_revno(revision_id)
            rev = self.branch.repository.get_revision(revision_id)
            nick = self.branch._get_nick()
            self._revision_cache[revision_id] = (revision, rev, nick)
            
        result.revision = revision
        result.committer = rev.committer
        result.message = rev.message
        result.timstamp = rev.timestamp
        # XXX no format_date, but probably this whole function
        # goes away soon
        result.revision_date = format_date(rev.timestamp, rev.timezone or 0)
        result.nick = nick
        return result
    
    def get_results(self, test_ids=None, revision_ids=None,
                    sorted_by_rev_date=True):
        # XXX we might want to build indexes for speed
        for result in self.results:
            if test_ids and result.test_id not in test_ids:
                continue
            if revision_ids and result.revision_id not in revision_ids:
                continue
            yield result

    def list_values_of(self, attr):
        """return a list of unique values of the specified attribute
        of PerfResult objects"""
        return dict.fromkeys((getattr(r, attr) for r in self.results)).keys()

    def get_testid2collections(self):
        """return a mapping of test_id to list of PerfResultCollection
        sorted by revision"""
        
        test_ids = self.list_values_of('test_id')
       
        testid2resultcollections = {}
        for test_id in test_ids:
            revnos = {}
            for result in self.get_results(test_ids=[test_id]): 
                revnos.setdefault(result.revision, []).append(result)
            for revno, results in revnos.iteritems():
                collection = PerfResultCollection(results)
                l = testid2resultcollections.setdefault(test_id, [])
                l.append(collection)
        # sort collection list by revision number
        for collections in testid2resultcollections.itervalues():
            collections.sort(lambda x,y: cmp(x.revision, y.revision))
        return testid2resultcollections