]> Git Repo - buildroot-mgba.git/commitdiff
support/scripts/graph-build-time: add support for timeline graphing
authorThomas Petazzoni <[email protected]>
Wed, 9 Feb 2022 20:30:26 +0000 (21:30 +0100)
committerYann E. MORIN <[email protected]>
Sun, 20 Mar 2022 22:52:24 +0000 (23:52 +0100)
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 <[email protected]>
[[email protected]:
  - sort by start-of-configure time
  - re-use existing colorsets (default or alternate)
  - fix python2isms
  - fix check-package
]
Signed-off-by: Yann E. MORIN <[email protected]>
Makefile
support/scripts/graph-build-time

index 3bbbdfbe01199e30a60bdfcfde3a800622a1adfc..05b790d770e3e5667b43ba03e94d5f579b208a7f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -871,6 +871,9 @@ graph-build: $(O)/build/build-time.log
                                   --type=pie-$(t) --input=$(<) \
                                   --output=$(GRAPHS_DIR)/build.pie-$(t).$(BR_GRAPH_OUT) \
                                   $(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
 graph-depends-requirements:
index 742c9a7a50837dc1fe6b868a96d330c2292fe82e..1edc3b3c00eca627000092eaf7fcfacbc4f7b842 100755 (executable)
@@ -241,6 +241,65 @@ def pkg_pie_time_per_step(data, 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
 # Package objects, filed with the duration of each step and the total
 # duration of the package.
@@ -277,7 +336,7 @@ def read_data(input_file):
 
 parser = argparse.ArgumentParser(description='Draw build time graphs')
 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",
                     help="Ordering of packages: build or duration (for histogram only)")
 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)
 elif args.type == "pie-steps":
     pkg_pie_time_per_step(d, args.output)
+elif args.type == "timeline":
+    pkg_timeline(d, args.output)
 else:
     sys.stderr.write("Unknown type: %s\n" % args.type)
     exit(1)
This page took 0.041841 seconds and 4 git commands to generate.