5 def acquire_time_data():
7 manager
= dbus
.Interface(bus
.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1'), 'org.freedesktop.systemd1.Manager')
8 units
= manager
.ListUnits()
16 properties
= dbus
.Interface(bus
.get_object('org.freedesktop.systemd1', i
[6]), 'org.freedesktop.DBus.Properties')
18 ixt
= int(properties
.Get('org.freedesktop.systemd1.Unit', 'InactiveExitTimestampMonotonic'))
19 aet
= int(properties
.Get('org.freedesktop.systemd1.Unit', 'ActiveEnterTimestampMonotonic'))
20 axt
= int(properties
.Get('org.freedesktop.systemd1.Unit', 'ActiveExitTimestampMonotonic'))
21 iet
= int(properties
.Get('org.freedesktop.systemd1.Unit', 'InactiveEnterTimestampMonotonic'))
23 l
.append((str(i
[0]), ixt
, aet
, axt
, iet
))
27 def acquire_start_time():
28 properties
= dbus
.Interface(bus
.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1'), 'org.freedesktop.DBus.Properties')
30 initrd_time
= int(properties
.Get('org.freedesktop.systemd1.Manager', 'InitRDTimestampMonotonic'))
31 startup_time
= int(properties
.Get('org.freedesktop.systemd1.Manager', 'StartupTimestampMonotonic'))
32 finish_time
= int(properties
.Get('org.freedesktop.systemd1.Manager', 'FinishTimestampMonotonic'))
34 assert initrd_time
<= startup_time
35 assert startup_time
<= finish_time
37 return initrd_time
, startup_time
, finish_time
39 def draw_box(context
, j
, k
, l
, m
, r
= 0, g
= 0, b
= 0):
41 context
.set_source_rgb(r
, g
, b
)
42 context
.rectangle(j
, k
, l
, m
)
46 def draw_text(context
, x
, y
, text
, size
= 12, r
= 0, g
= 0, b
= 0, vcenter
= 0.5, hcenter
= 0.5):
49 context
.set_source_rgb(r
, g
, b
)
50 context
.select_font_face("Sans", cairo
.FONT_SLANT_NORMAL
, cairo
.FONT_WEIGHT_NORMAL
)
51 context
.set_font_size(size
)
53 if vcenter
or hcenter
:
54 x_bearing
, y_bearing
, width
, height
= context
.text_extents(text
)[:4]
57 x
= x
- width
*hcenter
- x_bearing
60 y
= y
- height
*vcenter
- y_bearing
63 context
.show_text(text
)
68 sys
.stdout
.write("""systemd-analyze time
72 Process systemd profiling information
74 -h --help Show this help
78 bus
= dbus
.SystemBus()
80 if len(sys
.argv
) <= 1 or sys
.argv
[1] == 'time':
82 initrd_time
, start_time
, finish_time
= acquire_start_time()
85 print "Startup finished in %lums (kernel) + %lums (initrd) + %lums (userspace) = %lums" % ( \
87 (start_time
- initrd_time
)/1000, \
88 (finish_time
- start_time
)/1000, \
91 print "Startup finished in %lums (kernel) + %lums (userspace) = %lums" % ( \
93 (finish_time
- start_time
)/1000, \
97 elif sys
.argv
[1] == 'blame':
99 data
= acquire_time_data()
100 s
= sorted(data
, key
= lambda i
: i
[2] - i
[1], reverse
= True)
102 for name
, ixt
, aet
, axt
, iet
in s
:
104 if ixt
<= 0 or aet
<= 0:
110 sys
.stdout
.write("%6lums %s\n" % ((aet
- ixt
) / 1000, name
))
112 elif sys
.argv
[1] == 'plot':
115 initrd_time
, start_time
, finish_time
= acquire_start_time()
116 data
= acquire_time_data()
117 s
= sorted(data
, key
= lambda i
: i
[1])
121 for name
, ixt
, aet
, axt
, iet
in s
:
123 if (ixt
>= start_time
and ixt
<= finish_time
) or \
124 (aet
>= start_time
and aet
<= finish_time
) or \
125 (axt
>= start_time
and axt
<= finish_time
):
130 bar_space
= bar_height
* 0.1
132 # 1000px = 10s, 1px = 10ms
133 width
= (finish_time
- start_time
)/10000 + border
*2
134 height
= count
* (bar_height
+ bar_space
) + border
* 2
139 surface
= cairo
.SVGSurface(sys
.stdout
, width
, height
)
140 context
= cairo
.Context(surface
)
142 draw_box(context
, 0, 0, width
, height
, 1, 1, 1)
144 context
.translate(border
+ 0.5, border
+ 0.5)
147 context
.set_line_width(1)
148 context
.set_source_rgb(0.7, 0.7, 0.7)
150 for x
in range(0, (finish_time
- start_time
)/10000, 100):
151 context
.move_to(x
, 0)
152 context
.line_to(x
, height
-border
*2)
154 context
.move_to(0, 0)
155 context
.line_to(width
-border
*2, 0)
157 context
.move_to(0, height
-border
*2)
158 context
.line_to(width
-border
*2, height
-border
*2)
163 banner
= "Running on %s (%s %s) %s" % (os
.uname()[1], os
.uname()[2], os
.uname()[3], os
.uname()[4])
164 draw_text(context
, 0, -15, banner
, hcenter
= 0, vcenter
= 1)
166 for x
in range(0, (finish_time
- start_time
)/10000, 100):
167 draw_text(context
, x
, -5, "%lus" % (x
/100), vcenter
= 0, hcenter
= 0)
171 for name
, ixt
, aet
, axt
, iet
in s
:
176 if ixt
>= start_time
and ixt
<= finish_time
:
180 b
= min(filter(lambda x
: x
>= ixt
, (aet
, axt
, iet
, finish_time
))) - ixt
182 draw_box(context
, a
/10000, y
, b
/10000, bar_height
, 1, 0, 0)
188 if aet
>= start_time
and aet
<= finish_time
:
192 b
= min(filter(lambda x
: x
>= aet
, (axt
, iet
, finish_time
))) - aet
194 draw_box(context
, a
/10000, y
, b
/10000, bar_height
, .8, .6, .6)
200 if axt
>= start_time
and axt
<= finish_time
:
204 b
= min(filter(lambda x
: x
>= axt
, (iet
, finish_time
))) - axt
206 draw_box(context
, a
/10000, y
, b
/10000, bar_height
, .6, .4, .4)
215 if x
< width
/2-border
:
216 draw_text(context
, x
+ 10, y
+ bar_height
/2, name
, hcenter
= 0)
218 draw_text(context
, x
- 10, y
+ bar_height
/2, name
, hcenter
= 1)
220 y
+= bar_height
+ bar_space
222 draw_text(context
, 0, height
-border
*2, "Legend: Red = Activating; Pink = Active; Dark Pink = Deactivating", hcenter
= 0, vcenter
= -1)
225 elif sys
.argv
[1] in ("help", "--help", "-h"):
228 sys
.stderr
.write("Unknown verb '%s'.\n" % sys
.argv
[1])