3
# Copyright (C) 2009 Canonical Ltd
5
# This program is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License version 3 as
7
# published by the Free Software Foundation.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
# Authored by Gordon Allott <gord.allott@canonical.com>
26
from string import Template
27
from socket import gethostname
28
from datetime import datetime
32
header = Template("""Unity bootchart for $hostname ($date)
38
def sort_by_domain (x, y):
39
domain_x = x["name"].split("/")
40
domain_y = y["name"].split("/")
42
def recurse_domain (a, b, pos, xstart, ystart):
45
#check to see if the last item of the shortest is the same
46
if a[len(b)-1] == b[-1]:
49
#not in the same tree,
50
return int(ystart - xstart)
53
if b[len(a)-1] == a[-1]:
56
return int(ystart - xstart)
63
if (pos+2 > len(a) and pos+2 > len(b)):
64
return int(ystart - xstart)
67
return recurse_domain(a, b, pos+1, xstart, ystart)
75
return recurse_domain (domain_x, domain_y, 0, x['start'], y['start'])
78
def gatherinfo (filename):
79
date = datetime.fromtimestamp(os.path.getmtime(filename))
81
cpufile = open ("/proc/cpuinfo")
82
cpuinfo = cpufile.read (10024)
83
cpure = re.search (r"^model name\s*: (.*$)", cpuinfo, re.MULTILINE)
86
gpu_prog = subprocess.Popen("glxinfo", stdout=subprocess.PIPE)
88
gpuinfo = gpu_prog.stdout.read (10024)
89
gpure = re.search (r"^OpenGL renderer string: (.*$)", gpuinfo, re.MULTILINE)
92
return {"hostname":gethostname(),
93
"date": date.strftime("%A, %d. %B %Y %I:%M%p"),
94
"uname": " ".join (os.uname ()),
97
"total_time": "undefined"
100
width_multiplier = 1000
103
def draw_bg_graph (ctx, seconds, height):
105
total_width = seconds * width_multiplier
106
ctx.set_source_rgba (0.0, 0.0, 0.0, 0.25)
109
ctx.line_to (total_width, 0)
113
for pos in xrange (0, int(total_width), int (0.01 * width_multiplier)):
114
ctx.set_line_width (1)
115
ctx.set_source_rgba (0.0, 0.0, 0.0, 0.10)
118
ctx.set_line_width (2)
119
ctx.set_source_rgba (0.0, 0.0, 0.0, 0.25)
120
ctx.move_to (pos-6, -2)
121
ctx.show_text (str (pos / float(width_multiplier)))
125
ctx.line_to (pos, height)
135
def build_graph (data, filename, info):
144
if item['end'] > total_size:
145
total_size = item['end']
147
width = total_size * width_multiplier + padding_left + padding_right
148
height = len(data) * (bar_height+6) + 60 + padding_left + padding_right
149
surface = cairo.SVGSurface(filename, width, height)
151
ctx = cairo.Context (surface)
154
ctx.set_source_rgb (1, 1, 1)
155
ctx.rectangle (0, 0, width, height)
159
info['total_time'] = "%s secs" % total_size
160
sheader = header.substitute(info)
162
ctx.translate (padding_left, padding_right)
163
ctx.set_source_rgb (0, 0, 0)
164
for line in sheader.split("\n"):
165
ctx.translate (0, 12)
169
ctx.translate (0, 12)
171
draw_bg_graph (ctx, total_size, len (data) * bar_height + 16)
173
ctx.set_line_width (1)
175
x = item['start'] * width_multiplier
176
x1 = (item['end'] - item['start']) * width_multiplier
179
ctx.set_source_rgba (0.35, 0.65, 0.8, 0.5)
180
ctx.rectangle (0, 0, x1, 16)
183
ctx.set_source_rgba (0.35, 0.65, 0.8, 1.0)
184
ctx.rectangle (0, 0, x1, 16)
187
ctx.translate (8, 10)
188
ctx.set_source_rgb (0.0, 0.0, 0.0)
189
ctx.show_text (item['name'])
192
ctx.translate (-x-8, 6)
197
def build_data_structure (input):
198
reader = csv.reader(open(input))
200
print "reading", input
203
start = float(row[1])
205
structure.append ({"name": name, "start": start, "end": end})
211
print "use --input=filename.log and --output=filename.svg :)"
216
opts, args = getopt.getopt(sys.argv[1:], "h", ["help", "output=", "input="])
217
except getopt.GetoptError, err:
218
# print help information and exit:
219
print str(err) # will print something like "option -a not recognized"
226
if o in ("-h", "--help"):
229
elif o in ("--output"):
231
elif o in ("--input"):
234
assert False, "unhandled option"
236
if (not output or not input):
240
data = build_data_structure (input)
241
info = gatherinfo (input)
242
build_graph (data, output, info)
247
if __name__ == '__main__': main()