|
1 # |
|
2 # Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of the License "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 # Raptor log visualisation program. Takes a raptor log as standard input |
|
17 # and displays timelines that represent build progress and |
|
18 # how much actual parallelism there is in the build. |
|
19 # This program requires the pygame and PyOpenGL modules. |
|
20 |
|
21 from OpenGL.GL import * |
|
22 from OpenGL.GLU import * |
|
23 import pygame |
|
24 from pygame.locals import * |
|
25 import time |
|
26 |
|
27 class Timeline(object): |
|
28 |
|
29 globalmax = 2.0 |
|
30 |
|
31 def __init__(self,ylevel): |
|
32 self.maxtime = 0.0 |
|
33 self.recipes = [] |
|
34 self.ylevel = ylevel |
|
35 |
|
36 def append(self, recipe): |
|
37 if recipe.starttime + recipe.duration > self.maxtime: |
|
38 self.maxtime = recipe.starttime + recipe.duration |
|
39 if self.maxtime > Timeline.globalmax: |
|
40 Timeline.globalmax = self.maxtime |
|
41 #print "maxtime:",self.maxtime |
|
42 #print "xscale:",self.xscale |
|
43 else: |
|
44 pass |
|
45 #print "bob",self.maxtime |
|
46 |
|
47 self.recipes.append(recipe) |
|
48 |
|
49 def draw(self): |
|
50 glLoadIdentity() |
|
51 self.xscale = 4.0 / Timeline.globalmax |
|
52 |
|
53 glTranslatef(-2.0, -1.5, -6.0) |
|
54 count = 0 |
|
55 for r in self.recipes: |
|
56 if count % 2 == 0: |
|
57 coloff=0.8 |
|
58 else: |
|
59 coloff = 1.0 |
|
60 |
|
61 count += 1 |
|
62 r.draw(self.xscale, self.ylevel, coloff) |
|
63 |
|
64 class Recipe(object): |
|
65 STAT_OK = 0 |
|
66 colours = { |
|
67 'compile': (0.5,0.5,1.0), |
|
68 'compile2object': (0.5,0.5,1.0), |
|
69 'win32compile2object': (0.5,0.5,1.0), |
|
70 'tools2linkexe': (0.5,1.0,0.5), |
|
71 'link': (0.5,1.0,0.5), |
|
72 'win32stageonelink': (0.5,1.0,0.5), |
|
73 'tools2lib': (0.5,1.0,1.0), |
|
74 'win32stagetwolink': (1.0,0.1,1.0), |
|
75 'postlink': (1.0,0.5,1.0) |
|
76 } |
|
77 |
|
78 def __init__(self, starttime, duration, name, status): |
|
79 self.starttime = starttime |
|
80 self.duration = duration |
|
81 self.status = status |
|
82 self.colour = (1.0, 1.0, 1.0) |
|
83 if name in Recipe.colours: |
|
84 self.colour = Recipe.colours[name] |
|
85 else: |
|
86 self.colour = (1.0,1.0,1.0) |
|
87 self.name = name |
|
88 |
|
89 def draw(self, scale, ylevel, coloff): |
|
90 if self.status == Recipe.STAT_OK: |
|
91 glColor4f(self.colour[0]*coloff, self.colour[1]*coloff, self.colour[2]*coloff,0.2) |
|
92 else: |
|
93 glColor4f(1.0*coloff, 0.6*coloff, 0.6*coloff,0.2) |
|
94 |
|
95 print "ylevel: %s %f " % (self.name, ylevel) |
|
96 |
|
97 x = self.starttime * scale |
|
98 y = ylevel |
|
99 x2 = x + self.duration * scale |
|
100 y2 = ylevel + 0.2 |
|
101 glBegin(GL_QUADS) |
|
102 glVertex3f(x, y, 0) |
|
103 glVertex3f(x, y2, 0) |
|
104 glVertex3f(x2, y2, 0) |
|
105 glVertex3f(x2, y, 0) |
|
106 glEnd() |
|
107 |
|
108 |
|
109 def resize((width, height)): |
|
110 if height==0: |
|
111 height=1 |
|
112 glViewport(0, 0, width, height) |
|
113 glMatrixMode(GL_PROJECTION) |
|
114 glLoadIdentity() |
|
115 gluPerspective(45, 1.0*width/height, 0.1, 100.0) |
|
116 glMatrixMode(GL_MODELVIEW) |
|
117 glLoadIdentity() |
|
118 |
|
119 def init(): |
|
120 glShadeModel(GL_SMOOTH) |
|
121 glClearColor(0.0, 0.0, 0.0, 0.0) |
|
122 glClearDepth(1.0) |
|
123 glEnable(GL_DEPTH_TEST) |
|
124 glDepthFunc(GL_LEQUAL) |
|
125 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) |
|
126 |
|
127 |
|
128 import sys |
|
129 import re |
|
130 |
|
131 def main(): |
|
132 |
|
133 video_flags = OPENGL|DOUBLEBUF |
|
134 |
|
135 pygame.init() |
|
136 pygame.display.set_mode((800,600), video_flags) |
|
137 |
|
138 resize((800,600)) |
|
139 init() |
|
140 |
|
141 frames = 0 |
|
142 ticks = pygame.time.get_ticks() |
|
143 |
|
144 |
|
145 lines = 4 |
|
146 timelines = [] |
|
147 ylevel = 0.0 |
|
148 for i in xrange(0,4): |
|
149 ylevel += 0.6 |
|
150 timelines.append(Timeline(ylevel)) |
|
151 print "TIMELINE", ylevel |
|
152 |
|
153 f = sys.stdin |
|
154 |
|
155 recipe_re = re.compile(".*<recipe name='([^']+)'.*") |
|
156 time_re = re.compile(".*<time start='([0-9]+\.[0-9]+)' *elapsed='([0-9]+\.[0-9]+)'.*") |
|
157 status_re = re.compile(".*<status exit='([^']*)'.*") |
|
158 |
|
159 alternating = 0 |
|
160 start_time = 0.0 |
|
161 |
|
162 |
|
163 for l in f.xreadlines(): |
|
164 l2 = l.rstrip("\n") |
|
165 rm = recipe_re.match(l2) |
|
166 |
|
167 if rm is not None: |
|
168 rname = rm.groups()[0] |
|
169 continue |
|
170 |
|
171 |
|
172 tm = time_re.match(l2) |
|
173 if tm is not None: |
|
174 s = float(tm.groups()[0]) |
|
175 elapsed = float(tm.groups()[1]) |
|
176 |
|
177 if start_time == 0.0: |
|
178 start_time = s |
|
179 |
|
180 s -= start_time |
|
181 |
|
182 #print s,elapsed |
|
183 continue |
|
184 |
|
185 sm = status_re.match(l2) |
|
186 |
|
187 if sm is None: |
|
188 continue |
|
189 |
|
190 if sm.groups()[0] == 'ok': |
|
191 status = 0 |
|
192 else: |
|
193 status = int(sm.groups()[0]) |
|
194 |
|
195 olddiff = 999999999.0 |
|
196 tnum = 0 |
|
197 for t in timelines: |
|
198 newdiff = s - t.maxtime |
|
199 if newdiff < 0.0: |
|
200 continue |
|
201 #print "diff: %f" % (newdiff) |
|
202 if olddiff > newdiff: |
|
203 dest_timeline = t |
|
204 olddiff = newdiff |
|
205 #print "timeline selected: %d diff: %f" % (tnum,newdiff) |
|
206 tnum += 1 |
|
207 #print "----------" |
|
208 |
|
209 dest_timeline.append(Recipe(s, elapsed, rname, status)) |
|
210 event = pygame.event.poll() |
|
211 if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): |
|
212 break |
|
213 |
|
214 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) |
|
215 for t in timelines: |
|
216 t.draw() |
|
217 pygame.display.flip() |
|
218 |
|
219 frames = frames+1 |
|
220 |
|
221 print "fps: %de" % ((frames*1000)/(pygame.time.get_ticks()-ticks)) |
|
222 event = pygame.event.wait() |
|
223 |
|
224 |
|
225 if __name__ == '__main__': main() |