support/scripts/graph-build-time: add support for timeline graphing
This commit adds support for a new type of graph, showing the timeline of a build. It shows, with one line per package, when each of this package steps started/ended, and therefore allows to see the sequencing of the package builds. For a fully serialized build like we have today, this is not super useful (except to show that everything is serialized), but it becomes much more useful in the context of top-level parallel build. We chose to order the graph by the time-of-configure, as it is the closest to the actual cascade-style of a true dependency graph, which is tiny bit more complex to achieve properly. The actual result still looks pretty good. The graph-build make target is extended to also generate this new timeline graph. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> [yann.morin.1998@free.fr: - sort by start-of-configure time - re-use existing colorsets (default or alternate) - fix python2isms - fix check-package ] Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
This commit is contained in:
parent
842ba7ecef
commit
5e8b01afd5
3
Makefile
3
Makefile
@ -871,6 +871,9 @@ graph-build: $(O)/build/build-time.log
|
|||||||
--type=pie-$(t) --input=$(<) \
|
--type=pie-$(t) --input=$(<) \
|
||||||
--output=$(GRAPHS_DIR)/build.pie-$(t).$(BR_GRAPH_OUT) \
|
--output=$(GRAPHS_DIR)/build.pie-$(t).$(BR_GRAPH_OUT) \
|
||||||
$(if $(BR2_GRAPH_ALT),--alternate-colors)$(sep))
|
$(if $(BR2_GRAPH_ALT),--alternate-colors)$(sep))
|
||||||
|
./support/scripts/graph-build-time --type=timeline --input=$(<) \
|
||||||
|
--output=$(GRAPHS_DIR)/build.timeline.$(BR_GRAPH_OUT) \
|
||||||
|
$(if $(BR2_GRAPH_ALT),--alternate-colors)
|
||||||
|
|
||||||
.PHONY: graph-depends-requirements
|
.PHONY: graph-depends-requirements
|
||||||
graph-depends-requirements:
|
graph-depends-requirements:
|
||||||
|
@ -241,6 +241,65 @@ def pkg_pie_time_per_step(data, output):
|
|||||||
plt.savefig(output)
|
plt.savefig(output)
|
||||||
|
|
||||||
|
|
||||||
|
def pkg_timeline(data, output):
|
||||||
|
start = 0
|
||||||
|
end = 0
|
||||||
|
|
||||||
|
# Find the first timestamp and the last timestamp
|
||||||
|
for p in data:
|
||||||
|
for k, v in p.steps_start.items():
|
||||||
|
if start == 0 or v < start:
|
||||||
|
start = v
|
||||||
|
if end < v:
|
||||||
|
end = v
|
||||||
|
|
||||||
|
# Readjust all timestamps so that 0 is the start of the build
|
||||||
|
# instead of being Epoch
|
||||||
|
for p in data:
|
||||||
|
for k, v in p.steps_start.items():
|
||||||
|
p.steps_start[k] = v - start
|
||||||
|
for k, v in p.steps_end.items():
|
||||||
|
p.steps_end[k] = v - start
|
||||||
|
|
||||||
|
plt.figure()
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
labels_names = []
|
||||||
|
labels_coords = []
|
||||||
|
# put last packages that started to configure last; this does not
|
||||||
|
# give the proper dependency chain, but still provides a good-enough
|
||||||
|
# cascade graph.
|
||||||
|
for p in sorted(data, reverse=True, key=lambda x: x.steps_start['configure']):
|
||||||
|
durations = []
|
||||||
|
facecolors = []
|
||||||
|
for step in steps:
|
||||||
|
if step not in p.steps_start or step not in p.steps_end:
|
||||||
|
continue
|
||||||
|
durations.append((p.steps_start[step],
|
||||||
|
p.steps_end[step] - p.steps_start[step]))
|
||||||
|
facecolors.append(colors[steps.index(step)])
|
||||||
|
plt.broken_barh(durations, (i, 6), facecolors=facecolors)
|
||||||
|
labels_coords.append(i + 3)
|
||||||
|
labels_names.append(p.name)
|
||||||
|
i += 10
|
||||||
|
|
||||||
|
axes = plt.gcf().gca()
|
||||||
|
|
||||||
|
axes.set_ylim(0, i + 10)
|
||||||
|
axes.set_xlim(0, end - start)
|
||||||
|
axes.set_xlabel('seconds since start')
|
||||||
|
axes.set_yticks(labels_coords)
|
||||||
|
axes.set_yticklabels(labels_names)
|
||||||
|
axes.set_axisbelow(True)
|
||||||
|
axes.grid(True, linewidth=0.2, zorder=-1)
|
||||||
|
|
||||||
|
plt.gcf().subplots_adjust(left=0.2)
|
||||||
|
|
||||||
|
plt.tick_params(axis='y', which='both', labelsize=6)
|
||||||
|
plt.title('Timeline')
|
||||||
|
plt.savefig(output, dpi=300)
|
||||||
|
|
||||||
|
|
||||||
# Parses the csv file passed on standard input and returns a list of
|
# Parses the csv file passed on standard input and returns a list of
|
||||||
# Package objects, filed with the duration of each step and the total
|
# Package objects, filed with the duration of each step and the total
|
||||||
# duration of the package.
|
# duration of the package.
|
||||||
@ -277,7 +336,7 @@ def read_data(input_file):
|
|||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Draw build time graphs')
|
parser = argparse.ArgumentParser(description='Draw build time graphs')
|
||||||
parser.add_argument("--type", '-t', metavar="GRAPH_TYPE",
|
parser.add_argument("--type", '-t', metavar="GRAPH_TYPE",
|
||||||
help="Type of graph (histogram, pie-packages, pie-steps)")
|
help="Type of graph (histogram, pie-packages, pie-steps, timeline)")
|
||||||
parser.add_argument("--order", '-O', metavar="GRAPH_ORDER",
|
parser.add_argument("--order", '-O', metavar="GRAPH_ORDER",
|
||||||
help="Ordering of packages: build or duration (for histogram only)")
|
help="Ordering of packages: build or duration (for histogram only)")
|
||||||
parser.add_argument("--alternate-colors", '-c', action="store_true",
|
parser.add_argument("--alternate-colors", '-c', action="store_true",
|
||||||
@ -307,6 +366,8 @@ elif args.type == "pie-packages":
|
|||||||
pkg_pie_time_per_package(d, args.output)
|
pkg_pie_time_per_package(d, args.output)
|
||||||
elif args.type == "pie-steps":
|
elif args.type == "pie-steps":
|
||||||
pkg_pie_time_per_step(d, args.output)
|
pkg_pie_time_per_step(d, args.output)
|
||||||
|
elif args.type == "timeline":
|
||||||
|
pkg_timeline(d, args.output)
|
||||||
else:
|
else:
|
||||||
sys.stderr.write("Unknown type: %s\n" % args.type)
|
sys.stderr.write("Unknown type: %s\n" % args.type)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user