usec_t initrd_time;
usec_t userspace_time;
usec_t finish_time;
+ usec_t generators_start_time;
+ usec_t generators_finish_time;
+ usec_t unitsload_start_time;
+ usec_t unitsload_finish_time;
};
struct unit_times {
char *name;
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"FinishTimestampMonotonic",
- ×.finish_time) < 0)
+ ×.finish_time) < 0 ||
+ bus_get_uint64_property(bus,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GeneratorsStartTimestampMonotonic",
+ ×.generators_start_time) < 0 ||
+ bus_get_uint64_property(bus,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GeneratorsFinishTimestampMonotonic",
+ ×.generators_finish_time) < 0 ||
+ bus_get_uint64_property(bus,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "UnitsLoadStartTimestampMonotonic",
+ ×.unitsload_start_time) < 0 ||
+ bus_get_uint64_property(bus,
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "UnitsLoadFinishTimestampMonotonic",
+ ×.unitsload_finish_time) < 0)
return -EIO;
if (times.finish_time <= 0) {
svg("<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" "
"xmlns=\"http://www.w3.org/2000/svg\">\n\n",
- 80.0 + width, 150.0 + (m * SCALE_Y));
+ 80.0 + width, 150.0 + (m * SCALE_Y) +
+ 5 * SCALE_Y /* legend */);
/* write some basic info as a comment, including some help */
svg("<!-- This file is a systemd-analyze SVG file. It is best rendered in a -->\n"
" rect.firmware { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
" rect.loader { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
" rect.userspace { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
+ " rect.generators { fill: rgb(102,204,255); fill-opacity: 0.7; }\n"
+ " rect.unitsload { fill: rgb( 82,184,255); fill-opacity: 0.7; }\n"
" rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n"
" line { stroke: rgb(64,64,64); stroke-width: 1; }\n"
"// line.sec1 { }\n"
" line.sec5 { stroke-width: 2; }\n"
" line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n"
- " text { font-family: Verdana, Helvetica; font-size: 10; }\n"
- " text.left { font-family: Verdana, Helvetica; font-size: 10; text-anchor: start; }\n"
- " text.right { font-family: Verdana, Helvetica; font-size: 10; text-anchor: end; }\n"
- " text.sec { font-size: 8; }\n"
+ " text { font-family: Verdana, Helvetica; font-size: 14px; }\n"
+ " text.left { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: start; }\n"
+ " text.right { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: end; }\n"
+ " text.sec { font-size: 10px; }\n"
" ]]>\n </style>\n</defs>\n\n");
svg("<text x=\"20\" y=\"50\">%s</text>", pretty_times);
svg("<text x=\"20\" y=\"30\">%s %s (%s %s) %s</text>",
isempty(osname) ? "Linux" : osname,
name.nodename, name.release, name.version, name.machine);
- svg("<text x=\"20\" y=\"%.0f\">Legend: Red = Activating; Pink = Active; Dark Pink = Deactivating</text>",
- 120.0 + (m *SCALE_Y));
svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time));
svg_graph_box(m, -boot->firmware_time, boot->finish_time);
svg_text(true, boot->initrd_time, y, "initrd");
y++;
}
- svg_bar("userspace", boot->userspace_time, boot->finish_time, y);
- svg_text("left", boot->userspace_time, y, "userspace");
+ svg_bar("active", boot->userspace_time, boot->finish_time, y);
+ svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
+ svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
+ svg_text("left", boot->userspace_time, y, "systemd");
y++;
for (u = times; u < times + n; u++) {
svg_text(b, u->ixt, y, "%s", u->name);
y++;
}
+
+ /* Legend */
+ y++;
+ svg_bar("activating", 0, 300000, y);
+ svg_text("right", 400000, y, "Activating");
+ y++;
+ svg_bar("active", 0, 300000, y);
+ svg_text("right", 400000, y, "Active");
+ y++;
+ svg_bar("deactivating", 0, 300000, y);
+ svg_text("right", 400000, y, "Deactivating");
+ y++;
+ svg_bar("generators", 0, 300000, y);
+ svg_text("right", 400000, y, "Generators");
+ y++;
+ svg_bar("unitsload", 0, 300000, y);
+ svg_text("right", 400000, y, "Loading unit files");
+ y++;
+
+
svg("</g>\n\n");
svg("</svg>");
return 0;
}
-static int list_dependencies(DBusConnection *bus) {
+static int list_dependencies(DBusConnection *bus, const char *name) {
_cleanup_strv_free_ char **units = NULL;
char ts[FORMAT_TIMESPAN_MAX];
struct unit_times *times;
assert(bus);
- path = unit_dbus_path_from_name(SPECIAL_DEFAULT_TARGET);
+ path = unit_dbus_path_from_name(name);
if (path == NULL)
return -EINVAL;
printf("%s\n", id);
}
- return list_dependencies_one(bus, SPECIAL_DEFAULT_TARGET, 0, &units, 0);
+ return list_dependencies_one(bus, name, 0, &units, 0);
}
-static int analyze_critical_chain(DBusConnection *bus) {
+static int analyze_critical_chain(DBusConnection *bus, char *names[]) {
struct unit_times *times;
int n, r;
unsigned int i;
puts("The time after the unit is active or started is printed after the \"@\" character.\n"
"The time the unit takes to start is printed after the \"+\" character.\n");
- list_dependencies(bus);
+ if (!strv_isempty(names)) {
+ char **name;
+ STRV_FOREACH(name, names)
+ list_dependencies(bus, *name);
+ } else {
+ list_dependencies(bus, SPECIAL_DEFAULT_TARGET);
+ }
hashmap_free(h);
free_unit_times(times, (unsigned) n);
else if (streq(argv[optind], "blame"))
r = analyze_blame(bus);
else if (streq(argv[optind], "critical-chain"))
- r = analyze_critical_chain(bus);
+ r = analyze_critical_chain(bus, argv+optind+1);
else if (streq(argv[optind], "plot"))
r = analyze_plot(bus);
else if (streq(argv[optind], "dot"))