Buildroot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [Buildroot] [RFC] Build time graph generation
@ 2011-10-09 16:17 Thomas Petazzoni
  2011-10-09 16:17 ` [Buildroot] [PATCH 1/2] package: instrument to gather timing data Thomas Petazzoni
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Thomas Petazzoni @ 2011-10-09 16:17 UTC (permalink / raw)
  To: buildroot

Hello,

Here are two patches that implement a simple modification of the
package infrastructure to output some timing data about the duration
taken by each step for each package, and then a small Python script
that generates graphs from those informations.

I am not sure that there is any useful usage of those graphs, but it's
fun and there are nice to look at.

Here are some sample graphs, first on a moderately large package set:

 http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/histogram-build-order.pdf
 http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/histogram-duration-order.pdf
 http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/pie-packages.pdf
 http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/pie-steps.pdf

and then on a smaller package set:

 http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/histogram-build-order.pdf
 http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/histogram-duration-order.pdf
 http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/pie-packages.pdf
 http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/pie-steps.pdf

I don't think the modification to the package infrastructure is ready
for merging (there are many cases not handled, like when the timing
data should be cleaned up, the case of overriden packages not being
handled, etc.) and I am not even sure it is useful to complicate the
package infrastructure with such a not-so-useful feature.

Regards,

Thomas

The following changes since commit ddb8c639c312fd9f65dbb123837c100281495d50:

  libplayer: mark python bindings as broken (2011-10-08 22:39:29 +0200)

are available in the git repository at:
  http://free-electrons.com/~thomas/buildroot.git for-2011.11/graph-build-time

Thomas Petazzoni (2):
      package: instrument to gather timing data
      graph-build-time: generate graphs based on timing data

 package/Makefile.package.in      |   28 ++++
 support/scripts/graph-build-time |  252 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 280 insertions(+), 0 deletions(-)
 create mode 100755 support/scripts/graph-build-time

Thanks,
-- 
Thomas Petazzoni

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 1/2] package: instrument to gather timing data
  2011-10-09 16:17 [Buildroot] [RFC] Build time graph generation Thomas Petazzoni
@ 2011-10-09 16:17 ` Thomas Petazzoni
  2011-10-10 13:41   ` Thomas De Schampheleire
  2011-10-11  5:59   ` Arnout Vandecappelle
  2011-10-09 16:17 ` [Buildroot] [PATCH 2/2] graph-build-time: generate graphs based on " Thomas Petazzoni
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 15+ messages in thread
From: Thomas Petazzoni @ 2011-10-09 16:17 UTC (permalink / raw)
  To: buildroot

Instrument the package infrastructure to generate a
$(O)/build-time.data file which contains one line for each step of
each package and the corresponding duration in milliseconds.

The instrumentation is not perfect yet, as it doesn't account for
packages with overriden source directory and the build-time.data is
never removed, so results will accumulate if several partial builds
are done.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 package/Makefile.package.in |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/package/Makefile.package.in b/package/Makefile.package.in
index b5ef57b..605b518 100644
--- a/package/Makefile.package.in
+++ b/package/Makefile.package.in
@@ -254,6 +254,18 @@ define sep
 
 endef
 
+define savetime
+       echo $$(($$(date +%s%N)/1000000)) > $(O)/.br.time
+endef
+
+define outputtime
+       newtime=`echo $$(($$(date +%s%N)/1000000))` ; \
+       oldtime=`cat $(O)/.br.time` ; \
+       rm -f .br.time	      ; \
+       timediff=$$(($$newtime-$$oldtime)) ; \
+       echo "$(1),$(2),$$timediff" >> $(O)/build-time.data
+endef
+
 ################################################################################
 # Implicit targets -- produce a stamp file for each step of a package build
 ################################################################################
@@ -278,10 +290,12 @@ endif
 $(BUILD_DIR)/%/.stamp_extracted:
 	@$(call MESSAGE,"Extracting")
 	$(Q)mkdir -p $(@D)
+	$(call savetime)
 	$($(PKG)_EXTRACT_CMDS)
 # some packages have messed up permissions inside
 	$(Q)chmod -R +rw $(@D)
 	$(foreach hook,$($(PKG)_POST_EXTRACT_HOOKS),$(call $(hook))$(sep))
+	$(call outputtime,$($(PKG)_NAME),extract)
 	$(Q)touch $@
 
 # Rsync the source directory if the <pkg>_OVERRIDE_SRCDIR feature is
@@ -311,6 +325,7 @@ endif
 $(BUILD_DIR)/%/.stamp_patched: NAMEVER = $(RAWNAME)-$($(PKG)_VERSION)
 $(BUILD_DIR)/%/.stamp_patched:
 	@$(call MESSAGE,"Patching $($(PKG)_DIR_PREFIX)/$(RAWNAME)")
+	$(call savetime)
 	$(foreach hook,$($(PKG)_PRE_PATCH_HOOKS),$(call $(hook))$(sep))
 	$(if $($(PKG)_PATCH),support/scripts/apply-patches.sh $(@D) $(DL_DIR) $($(PKG)_PATCH))
 	$(Q)( \
@@ -326,49 +341,62 @@ $(BUILD_DIR)/%/.stamp_patched:
 	fi; \
 	)
 	$(foreach hook,$($(PKG)_POST_PATCH_HOOKS),$(call $(hook))$(sep))
+	$(call outputtime,$($(PKG)_NAME),patch)
 	$(Q)touch $@
 
 # Configure
 $(BUILD_DIR)/%/.stamp_configured:
+	$(call savetime)
 	$(foreach hook,$($(PKG)_PRE_CONFIGURE_HOOKS),$(call $(hook))$(sep))
 	@$(call MESSAGE,"Configuring")
 	$($(PKG)_CONFIGURE_CMDS)
 	$(foreach hook,$($(PKG)_POST_CONFIGURE_HOOKS),$(call $(hook))$(sep))
+	$(call outputtime,$($(PKG)_NAME),configure)
 	$(Q)touch $@
 
 # Build
 $(BUILD_DIR)/%/.stamp_built::
 	@$(call MESSAGE,"Building")
+	$(call savetime)
 	$($(PKG)_BUILD_CMDS)
 	$(foreach hook,$($(PKG)_POST_BUILD_HOOKS),$(call $(hook))$(sep))
+	$(call outputtime,$($(PKG)_NAME),build)
 	$(Q)touch $@
 
 # Install to host dir
 $(BUILD_DIR)/%/.stamp_host_installed:
 	@$(call MESSAGE,"Installing to host directory")
+	$(call savetime)
 	$($(PKG)_INSTALL_CMDS)
 	$(foreach hook,$($(PKG)_POST_INSTALL_HOOKS),$(call $(hook))$(sep))
+	$(call outputtime,$($(PKG)_NAME),install-host)
 	$(Q)touch $@
 
 # Install to staging dir
 $(BUILD_DIR)/%/.stamp_staging_installed:
 	@$(call MESSAGE,"Installing to staging directory")
+	$(call savetime)
 	$($(PKG)_INSTALL_STAGING_CMDS)
 	$(foreach hook,$($(PKG)_POST_INSTALL_STAGING_HOOKS),$(call $(hook))$(sep))
+	$(call outputtime,$($(PKG)_NAME),install-staging)
 	$(Q)touch $@
 
 # Install to images dir
 $(BUILD_DIR)/%/.stamp_images_installed:
 	@$(call MESSAGE,"Installing to images directory")
+	$(call savetime)
 	$($(PKG)_INSTALL_IMAGES_CMDS)
 	$(foreach hook,$($(PKG)_POST_INSTALL_IMAGES_HOOKS),$(call $(hook))$(sep))
+	$(call outputtime,$($(PKG)_NAME),install-images)
 	$(Q)touch $@
 
 # Install to target dir
 $(BUILD_DIR)/%/.stamp_target_installed:
 	@$(call MESSAGE,"Installing to target")
+	$(call savetime)
 	$($(PKG)_INSTALL_TARGET_CMDS)
 	$(foreach hook,$($(PKG)_POST_INSTALL_TARGET_HOOKS),$(call $(hook))$(sep))
+	$(call outputtime,$($(PKG)_NAME),install-target)
 	$(Q)touch $@
 
 # Clean package
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 2/2] graph-build-time: generate graphs based on timing data
  2011-10-09 16:17 [Buildroot] [RFC] Build time graph generation Thomas Petazzoni
  2011-10-09 16:17 ` [Buildroot] [PATCH 1/2] package: instrument to gather timing data Thomas Petazzoni
@ 2011-10-09 16:17 ` Thomas Petazzoni
  2011-10-10 13:12   ` Thomas De Schampheleire
  2011-10-10  9:32 ` [Buildroot] [RFC] Build time graph generation Diego Iastrubni
  2011-10-10 13:55 ` Thomas De Schampheleire
  3 siblings, 1 reply; 15+ messages in thread
From: Thomas Petazzoni @ 2011-10-09 16:17 UTC (permalink / raw)
  To: buildroot

This script generates graphs of packages build time, from the timing
data generated by Buildroot in the $(O)/build-time.data file.

Example usage:

  cat $(O)/build-time.data | \
      ./support/scripts/graph-build-time \
      --type=histogram --output=foobar.pdf

Three graph types are available :

  * histogram, which creates an histogram of the build time for each
    package, decomposed by each step (extract, patch, configure,
    etc.). The order in which the packages are shown is
    configurable: by build order, or by duration order. See the
    --order option.

  * pie-packages, which creates a pie chart of the build time of
    each package (without decomposition in steps). Packages that
    contributed to less than 1% of the overall build time are all
    grouped together in an "Other" entry.

  * pie-steps, which creates a pie chart of the time spent globally
    on each step (extract, patch, configure, etc...)

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 support/scripts/graph-build-time |  252 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 252 insertions(+), 0 deletions(-)
 create mode 100755 support/scripts/graph-build-time

diff --git a/support/scripts/graph-build-time b/support/scripts/graph-build-time
new file mode 100755
index 0000000..7fde852
--- /dev/null
+++ b/support/scripts/graph-build-time
@@ -0,0 +1,252 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2011 by Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# This script generates graphs of packages build time, from the timing
+# data generated by Buildroot in the $(O)/build-time.data file.
+#
+# Example usage:
+#
+#   cat $(O)/build-time.data | ./support/scripts/graph-build-time --type=histogram --output=foobar.pdf
+#
+# Three graph types are available :
+#
+#   * histogram, which creates an histogram of the build time for each
+#     package, decomposed by each step (extract, patch, configure,
+#     etc.). The order in which the packages are shown is
+#     configurable: by build order, or by duration order. See the
+#     --order option.
+#
+#   * pie-packages, which creates a pie chart of the build time of
+#     each package (without decomposition in steps). Packages that
+#     contributed to less than 1% of the overall build time are all
+#     grouped together in an "Other" entry.
+#
+#   * pie-steps, which creates a pie chart of the time spent globally
+#     on each step (extract, patch, configure, etc...)
+#
+# Requirements:
+#
+#   * matplotlib (python-matplotlib on Debian/Ubuntu systems)
+#   * numpy (python-numpy on Debian/Ubuntu systems)
+#   * argparse (by default in Python 2.7, requires python-argparse if
+#     Python 2.6 is used)
+
+import matplotlib
+import numpy
+matplotlib.use('PDF')
+
+import matplotlib.pyplot as plt
+import matplotlib.font_manager as fm
+import csv
+import argparse
+import sys
+
+steps = [ 'extract', 'patch', 'configure', 'build',
+          'install-target', 'install-host', 'install-images',
+          'install-staging' ]
+
+histogram_colors = ['#e60004', '#009836', '#2e1d86', '#ffed00',
+                    '#0068b5', '#f28e00', '#940084', '#97c000',
+                    '#00469b', '#f9c000' ]
+
+class Package:
+    def __init__(self, name):
+        self.name = name
+        self.steps_duration = {}
+        self.duration = 0
+
+    def add_step(self, step, duration):
+        self.steps_duration[step] = duration
+        self.duration += duration
+
+    def get_duration(self, step):
+        if self.steps_duration.has_key(step):
+            return self.steps_duration[step]
+        else:
+            return 0
+
+# Generate an histogram of the time spent in each step of each
+# package.
+def pkg_histogram(data, output, order="build"):
+    n_pkgs = len(data)
+    ind = numpy.arange(n_pkgs)
+
+    if order == "duration":
+        data = sorted(data, key=lambda p: p.duration, reverse=True)
+
+    # Prepare the vals array, containing one entry for each step
+    vals = []
+    for step in steps:
+        val = []
+        for p in data:
+            val.append(p.get_duration(step))
+        vals.append(val)
+
+    bottom = [0] * n_pkgs
+    legenditems = []
+
+    plt.figure()
+
+    # Draw the bars, step by step
+    for i in range(0, len(vals)):
+        b = plt.bar(ind, vals[i], 1, color=histogram_colors[i], bottom=bottom, linewidth=0)
+        legenditems.append(b[0])
+        bottom = [ bottom[j] + vals[i][j] for j in range(0, len(vals[i])) ]
+
+    # Draw the package names
+    plt.xticks(ind + .5, [ p.name for p in data ], rotation=90, fontsize=4)
+
+    # Adjust size of graph (double the width)
+    sz = plt.gcf().get_size_inches()
+    plt.gcf().set_size_inches(sz[0] * 2, sz[1])
+
+    # Add more space for the package names at the bottom
+    plt.gcf().subplots_adjust(bottom=0.2)
+
+    # Remove ticks in the graph for each package
+    axes = plt.gcf().gca()
+    for line in axes.get_xticklines():
+        line.set_markersize(0)
+
+    axes.set_ylabel('Time (seconds)')
+
+    # Reduce size of legend text
+    leg_prop = fm.FontProperties(size=6)
+
+    # Draw legend
+    plt.legend(legenditems, steps, prop=leg_prop)
+
+    if order == "build":
+        plt.title('Build time of packages, by build order')
+    elif order == "duration":
+        plt.title('Build time of packages, by duration order')
+
+    # Save graph
+    plt.savefig(output)
+
+# Generate a pie chart with the time spent building each package.
+def pkg_pie_time_per_package(data, output):
+    # Compute total build duration
+    total = 0
+    for p in data:
+        total += p.duration
+
+    # Build the list of labels and values, and filter the packages
+    # that account for less than 1% of the build time.
+    labels = []
+    values = []
+    other_value = 0
+    for p in data:
+        if p.duration < (total * 0.01):
+            other_value += p.duration
+        else:
+            labels.append(p.name)
+            values.append(p.duration)
+
+    labels.append('Other')
+    values.append(other_value)
+
+    plt.figure()
+
+    # Draw pie graph
+    patches, texts, autotexts = plt.pie(values, labels=labels, autopct='%1.1f%%', shadow=True)
+
+    # Reduce text size
+    proptease = fm.FontProperties()
+    proptease.set_size('xx-small')
+    plt.setp(autotexts, fontproperties=proptease)
+    plt.setp(texts, fontproperties=proptease)
+
+    plt.title('Build time per package')
+    plt.savefig(output)
+
+# Generate a pie chart with a portion for the overall time spent in
+# each step for all packages.
+def pkg_pie_time_per_step(data, output):
+    steps_values = []
+    for step in steps:
+        val = 0
+        for p in data:
+            val += p.get_duration(step)
+        steps_values.append(val)
+
+    plt.figure()
+
+    # Draw pie graph
+    patches, texts, autotexts = plt.pie(steps_values, labels=steps,
+                                        autopct='%1.1f%%', shadow=True)
+
+    # Reduce text size
+    proptease = fm.FontProperties()
+    proptease.set_size('xx-small')
+    plt.setp(autotexts, fontproperties=proptease)
+    plt.setp(texts, fontproperties=proptease)
+
+    plt.title('Build time per step')
+    plt.savefig(output)
+
+# 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.
+def read_data():
+    reader = csv.reader(sys.stdin, delimiter=',')
+    pkgs = []
+
+    # Auxilliary function to find a package by name in the list.
+    def getpkg(name):
+        for p in pkgs:
+            if p.name == name:
+                return p
+        return None
+
+    for row in reader:
+        pkg = row[0]
+        step = row[1]
+        duration = float(row[2]) / 1000.
+
+        p = getpkg(pkg)
+        if p is None:
+            p = Package(pkg)
+            pkgs.append(p)
+
+        p.add_step(step, duration)
+
+    return pkgs
+
+parser = argparse.ArgumentParser(description='Draw build time graphs')
+parser.add_argument("--type", metavar="GRAPH_TYPE", required=True,
+                    help="Type of graph (histogram, pie-packages, pie-steps)")
+parser.add_argument("--order", metavar="GRAPH_ORDER",
+                    help="Ordering of packages: build or duration (for histogram only)")
+parser.add_argument("--output", metavar="OUTPUT", required=True,
+                    help="Output file (PDF extension)")
+args = parser.parse_args()
+
+d = read_data()
+
+if args.type == "histogram":
+    if args.order == "build" or args.order == "duration":
+        pkg_histogram(d, args.output, args.order)
+    else:
+        print "Unknown graph order"
+        sys.exit(1)
+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)
+
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Buildroot] [RFC] Build time graph generation
  2011-10-09 16:17 [Buildroot] [RFC] Build time graph generation Thomas Petazzoni
  2011-10-09 16:17 ` [Buildroot] [PATCH 1/2] package: instrument to gather timing data Thomas Petazzoni
  2011-10-09 16:17 ` [Buildroot] [PATCH 2/2] graph-build-time: generate graphs based on " Thomas Petazzoni
@ 2011-10-10  9:32 ` Diego Iastrubni
  2011-10-10 13:55 ` Thomas De Schampheleire
  3 siblings, 0 replies; 15+ messages in thread
From: Diego Iastrubni @ 2011-10-10  9:32 UTC (permalink / raw)
  To: buildroot

On Sun, Oct 9, 2011 at 6:17 PM, Thomas Petazzoni <
thomas.petazzoni@free-electrons.com> wrote:

> Here are two patches that implement a simple modification of the
> package infrastructure to output some timing data about the duration
> taken by each step for each package, and then a small Python script
> that generates graphs from those informations.
>
> I am not sure that there is any useful usage of those graphs, but it's
> fun and there are nice to look at.
>
> Here are some sample graphs, first on a moderately large package set:
>
>
> http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/histogram-build-order.pdf
>
> http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/histogram-duration-order.pdf
>
> http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/pie-packages.pdf
>
> http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/pie-steps.pdf
>
> and then on a smaller package set:
>
>
> http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/histogram-build-order.pdf
>
> http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/histogram-duration-order.pdf
>
> http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/pie-packages.pdf
>
> http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/pie-steps.pdf
>
> I don't think the modification to the package infrastructure is ready
> for merging (there are many cases not handled, like when the timing
> data should be cleaned up, the case of overriden packages not being
> handled, etc.) and I am not even sure it is useful to complicate the
> package infrastructure with such a not-so-useful feature.
>

Nice, that would be a great feature to add. Even better if you can save the
whole charts in the same doc :)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.busybox.net/pipermail/buildroot/attachments/20111010/c4ef8786/attachment.html>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 2/2] graph-build-time: generate graphs based on timing data
  2011-10-09 16:17 ` [Buildroot] [PATCH 2/2] graph-build-time: generate graphs based on " Thomas Petazzoni
@ 2011-10-10 13:12   ` Thomas De Schampheleire
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas De Schampheleire @ 2011-10-10 13:12 UTC (permalink / raw)
  To: buildroot

Hi,

On Sun, Oct 9, 2011 at 6:17 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
> This script generates graphs of packages build time, from the timing
> data generated by Buildroot in the $(O)/build-time.data file.
>
> Example usage:
>
> ?cat $(O)/build-time.data | \
> ? ? ?./support/scripts/graph-build-time \
> ? ? ?--type=histogram --output=foobar.pdf
>
> Three graph types are available :
>
> ?* histogram, which creates an histogram of the build time for each
> ? ?package, decomposed by each step (extract, patch, configure,
> ? ?etc.). The order in which the packages are shown is
> ? ?configurable: by build order, or by duration order. See the
> ? ?--order option.
>
> ?* pie-packages, which creates a pie chart of the build time of
> ? ?each package (without decomposition in steps). Packages that
> ? ?contributed to less than 1% of the overall build time are all
> ? ?grouped together in an "Other" entry.
>
> ?* pie-steps, which creates a pie chart of the time spent globally
> ? ?on each step (extract, patch, configure, etc...)
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
> ?support/scripts/graph-build-time | ?252 ++++++++++++++++++++++++++++++++++++++
> ?1 files changed, 252 insertions(+), 0 deletions(-)
> ?create mode 100755 support/scripts/graph-build-time
>
> diff --git a/support/scripts/graph-build-time b/support/scripts/graph-build-time
> new file mode 100755
> index 0000000..7fde852
> --- /dev/null
> +++ b/support/scripts/graph-build-time
> @@ -0,0 +1,252 @@
> +#!/usr/bin/env python
> +
> +# Copyright (C) 2011 by Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +# General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> +
> +# This script generates graphs of packages build time, from the timing
> +# data generated by Buildroot in the $(O)/build-time.data file.
> +#
> +# Example usage:
> +#
> +# ? cat $(O)/build-time.data | ./support/scripts/graph-build-time --type=histogram --output=foobar.pdf
> +#
> +# Three graph types are available :
> +#
> +# ? * histogram, which creates an histogram of the build time for each
> +# ? ? package, decomposed by each step (extract, patch, configure,
> +# ? ? etc.). The order in which the packages are shown is
> +# ? ? configurable: by build order, or by duration order. See the
> +# ? ? --order option.
> +#
> +# ? * pie-packages, which creates a pie chart of the build time of
> +# ? ? each package (without decomposition in steps). Packages that
> +# ? ? contributed to less than 1% of the overall build time are all
> +# ? ? grouped together in an "Other" entry.
> +#
> +# ? * pie-steps, which creates a pie chart of the time spent globally
> +# ? ? on each step (extract, patch, configure, etc...)
> +#
> +# Requirements:
> +#
> +# ? * matplotlib (python-matplotlib on Debian/Ubuntu systems)
> +# ? * numpy (python-numpy on Debian/Ubuntu systems)
> +# ? * argparse (by default in Python 2.7, requires python-argparse if
> +# ? ? Python 2.6 is used)
> +
> +import matplotlib
> +import numpy
> +matplotlib.use('PDF')
> +
> +import matplotlib.pyplot as plt
> +import matplotlib.font_manager as fm
> +import csv
> +import argparse
> +import sys
> +
> +steps = [ 'extract', 'patch', 'configure', 'build',
> + ? ? ? ? ?'install-target', 'install-host', 'install-images',
> + ? ? ? ? ?'install-staging' ]
> +
> +histogram_colors = ['#e60004', '#009836', '#2e1d86', '#ffed00',
> + ? ? ? ? ? ? ? ? ? ?'#0068b5', '#f28e00', '#940084', '#97c000',
> + ? ? ? ? ? ? ? ? ? ?'#00469b', '#f9c000' ]
> +
> +class Package:
> + ? ?def __init__(self, name):
> + ? ? ? ?self.name = name
> + ? ? ? ?self.steps_duration = {}
> + ? ? ? ?self.duration = 0
> +
> + ? ?def add_step(self, step, duration):
> + ? ? ? ?self.steps_duration[step] = duration
> + ? ? ? ?self.duration += duration
> +
> + ? ?def get_duration(self, step):
> + ? ? ? ?if self.steps_duration.has_key(step):
> + ? ? ? ? ? ?return self.steps_duration[step]
> + ? ? ? ?else:
> + ? ? ? ? ? ?return 0
> +
> +# Generate an histogram of the time spent in each step of each
> +# package.
> +def pkg_histogram(data, output, order="build"):
> + ? ?n_pkgs = len(data)
> + ? ?ind = numpy.arange(n_pkgs)
> +
> + ? ?if order == "duration":
> + ? ? ? ?data = sorted(data, key=lambda p: p.duration, reverse=True)
> +
> + ? ?# Prepare the vals array, containing one entry for each step
> + ? ?vals = []
> + ? ?for step in steps:
> + ? ? ? ?val = []
> + ? ? ? ?for p in data:
> + ? ? ? ? ? ?val.append(p.get_duration(step))
> + ? ? ? ?vals.append(val)

This could be simplified somewhat with list comprehensions (in
progressive forms of simplification):
vals = []
for step in steps:
    val = [ p.get_duration(step) for p in data ]
    vals.append(val)


vals = []
for step in steps:
    vals.append( [ p.get_duration(step) for p in data ] )


vals = [ [ p.get_duration(step) for p in data ] for step in steps ]

At least, to me this is simpler to understand, maybe you prefer the
unwound approach.

> +
> + ? ?bottom = [0] * n_pkgs
> + ? ?legenditems = []
> +
> + ? ?plt.figure()
> +
> + ? ?# Draw the bars, step by step
> + ? ?for i in range(0, len(vals)):
> + ? ? ? ?b = plt.bar(ind, vals[i], 1, color=histogram_colors[i], bottom=bottom, linewidth=0)
> + ? ? ? ?legenditems.append(b[0])
> + ? ? ? ?bottom = [ bottom[j] + vals[i][j] for j in range(0, len(vals[i])) ]
> +
> + ? ?# Draw the package names
> + ? ?plt.xticks(ind + .5, [ p.name for p in data ], rotation=90, fontsize=4)
> +
> + ? ?# Adjust size of graph (double the width)
> + ? ?sz = plt.gcf().get_size_inches()
> + ? ?plt.gcf().set_size_inches(sz[0] * 2, sz[1])
> +
> + ? ?# Add more space for the package names at the bottom
> + ? ?plt.gcf().subplots_adjust(bottom=0.2)
> +
> + ? ?# Remove ticks in the graph for each package
> + ? ?axes = plt.gcf().gca()
> + ? ?for line in axes.get_xticklines():
> + ? ? ? ?line.set_markersize(0)
> +
> + ? ?axes.set_ylabel('Time (seconds)')
> +
> + ? ?# Reduce size of legend text
> + ? ?leg_prop = fm.FontProperties(size=6)
> +
> + ? ?# Draw legend
> + ? ?plt.legend(legenditems, steps, prop=leg_prop)
> +
> + ? ?if order == "build":
> + ? ? ? ?plt.title('Build time of packages, by build order')
> + ? ?elif order == "duration":
> + ? ? ? ?plt.title('Build time of packages, by duration order')
> +
> + ? ?# Save graph
> + ? ?plt.savefig(output)
> +
> +# Generate a pie chart with the time spent building each package.
> +def pkg_pie_time_per_package(data, output):
> + ? ?# Compute total build duration
> + ? ?total = 0
> + ? ?for p in data:
> + ? ? ? ?total += p.duration
> +
> + ? ?# Build the list of labels and values, and filter the packages
> + ? ?# that account for less than 1% of the build time.
> + ? ?labels = []
> + ? ?values = []
> + ? ?other_value = 0
> + ? ?for p in data:
> + ? ? ? ?if p.duration < (total * 0.01):
> + ? ? ? ? ? ?other_value += p.duration
> + ? ? ? ?else:
> + ? ? ? ? ? ?labels.append(p.name)
> + ? ? ? ? ? ?values.append(p.duration)
> +
> + ? ?labels.append('Other')
> + ? ?values.append(other_value)
> +
> + ? ?plt.figure()
> +
> + ? ?# Draw pie graph
> + ? ?patches, texts, autotexts = plt.pie(values, labels=labels, autopct='%1.1f%%', shadow=True)
> +
> + ? ?# Reduce text size
> + ? ?proptease = fm.FontProperties()
> + ? ?proptease.set_size('xx-small')
> + ? ?plt.setp(autotexts, fontproperties=proptease)
> + ? ?plt.setp(texts, fontproperties=proptease)
> +
> + ? ?plt.title('Build time per package')
> + ? ?plt.savefig(output)
> +
> +# Generate a pie chart with a portion for the overall time spent in
> +# each step for all packages.
> +def pkg_pie_time_per_step(data, output):
> + ? ?steps_values = []
> + ? ?for step in steps:
> + ? ? ? ?val = 0
> + ? ? ? ?for p in data:
> + ? ? ? ? ? ?val += p.get_duration(step)
> + ? ? ? ?steps_values.append(val)
> +
> + ? ?plt.figure()
> +
> + ? ?# Draw pie graph
> + ? ?patches, texts, autotexts = plt.pie(steps_values, labels=steps,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?autopct='%1.1f%%', shadow=True)
> +
> + ? ?# Reduce text size
> + ? ?proptease = fm.FontProperties()
> + ? ?proptease.set_size('xx-small')
> + ? ?plt.setp(autotexts, fontproperties=proptease)
> + ? ?plt.setp(texts, fontproperties=proptease)
> +
> + ? ?plt.title('Build time per step')
> + ? ?plt.savefig(output)
> +
> +# 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.
> +def read_data():
> + ? ?reader = csv.reader(sys.stdin, delimiter=',')
> + ? ?pkgs = []
> +
> + ? ?# Auxilliary function to find a package by name in the list.
> + ? ?def getpkg(name):
> + ? ? ? ?for p in pkgs:
> + ? ? ? ? ? ?if p.name == name:
> + ? ? ? ? ? ? ? ?return p
> + ? ? ? ?return None
> +
> + ? ?for row in reader:
> + ? ? ? ?pkg = row[0]
> + ? ? ? ?step = row[1]
> + ? ? ? ?duration = float(row[2]) / 1000.
> +
> + ? ? ? ?p = getpkg(pkg)
> + ? ? ? ?if p is None:
> + ? ? ? ? ? ?p = Package(pkg)
> + ? ? ? ? ? ?pkgs.append(p)
> +
> + ? ? ? ?p.add_step(step, duration)
> +
> + ? ?return pkgs
> +
> +parser = argparse.ArgumentParser(description='Draw build time graphs')
> +parser.add_argument("--type", metavar="GRAPH_TYPE", required=True,
> + ? ? ? ? ? ? ? ? ? ?help="Type of graph (histogram, pie-packages, pie-steps)")
> +parser.add_argument("--order", metavar="GRAPH_ORDER",
> + ? ? ? ? ? ? ? ? ? ?help="Ordering of packages: build or duration (for histogram only)")
> +parser.add_argument("--output", metavar="OUTPUT", required=True,
> + ? ? ? ? ? ? ? ? ? ?help="Output file (PDF extension)")
> +args = parser.parse_args()
> +
> +d = read_data()
> +
> +if args.type == "histogram":
> + ? ?if args.order == "build" or args.order == "duration":
> + ? ? ? ?pkg_histogram(d, args.output, args.order)
> + ? ?else:
> + ? ? ? ?print "Unknown graph order"
> + ? ? ? ?sys.exit(1)
> +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)
> +

Best regards,
Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 1/2] package: instrument to gather timing data
  2011-10-09 16:17 ` [Buildroot] [PATCH 1/2] package: instrument to gather timing data Thomas Petazzoni
@ 2011-10-10 13:41   ` Thomas De Schampheleire
  2011-10-11  5:59     ` Arnout Vandecappelle
  2011-10-11  5:59   ` Arnout Vandecappelle
  1 sibling, 1 reply; 15+ messages in thread
From: Thomas De Schampheleire @ 2011-10-10 13:41 UTC (permalink / raw)
  To: buildroot

Hi,

On Sun, Oct 9, 2011 at 6:17 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
> Instrument the package infrastructure to generate a
> $(O)/build-time.data file which contains one line for each step of
> each package and the corresponding duration in milliseconds.
>
> The instrumentation is not perfect yet, as it doesn't account for
> packages with overriden source directory and the build-time.data is
> never removed, so results will accumulate if several partial builds
> are done.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
> ?package/Makefile.package.in | ? 28 ++++++++++++++++++++++++++++
> ?1 files changed, 28 insertions(+), 0 deletions(-)
>
> diff --git a/package/Makefile.package.in b/package/Makefile.package.in
> index b5ef57b..605b518 100644
> --- a/package/Makefile.package.in
> +++ b/package/Makefile.package.in
> @@ -254,6 +254,18 @@ define sep
>
> ?endef
>
> +define savetime
> + ? ? ? echo $$(($$(date +%s%N)/1000000)) > $(O)/.br.time
> +endef
> +
> +define outputtime
> + ? ? ? newtime=`echo $$(($$(date +%s%N)/1000000))` ; \
> + ? ? ? oldtime=`cat $(O)/.br.time` ; \
> + ? ? ? rm -f .br.time ? ? ? ?; \
> + ? ? ? timediff=$$(($$newtime-$$oldtime)) ; \
> + ? ? ? echo "$(1),$(2),$$timediff" >> $(O)/build-time.data
> +endef
> +

What about placing these functions in a separate file, like
package/build-time.in ? It keeps Makefile.package.in a bit cleaner.

And what about making this behavior selectable, i.e. only if a certain
config option is set, will data be gathered. In the other case,
'savetime' and 'outputtime' can be empty functions.

> ?################################################################################
> ?# Implicit targets -- produce a stamp file for each step of a package build
> ?################################################################################
> @@ -278,10 +290,12 @@ endif
> ?$(BUILD_DIR)/%/.stamp_extracted:
> ? ? ? ?@$(call MESSAGE,"Extracting")
> ? ? ? ?$(Q)mkdir -p $(@D)
> + ? ? ? $(call savetime)
> ? ? ? ?$($(PKG)_EXTRACT_CMDS)
> ?# some packages have messed up permissions inside
> ? ? ? ?$(Q)chmod -R +rw $(@D)
> ? ? ? ?$(foreach hook,$($(PKG)_POST_EXTRACT_HOOKS),$(call $(hook))$(sep))
> + ? ? ? $(call outputtime,$($(PKG)_NAME),extract)
> ? ? ? ?$(Q)touch $@
>
> ?# Rsync the source directory if the <pkg>_OVERRIDE_SRCDIR feature is
> @@ -311,6 +325,7 @@ endif
> ?$(BUILD_DIR)/%/.stamp_patched: NAMEVER = $(RAWNAME)-$($(PKG)_VERSION)
> ?$(BUILD_DIR)/%/.stamp_patched:
> ? ? ? ?@$(call MESSAGE,"Patching $($(PKG)_DIR_PREFIX)/$(RAWNAME)")
> + ? ? ? $(call savetime)
> ? ? ? ?$(foreach hook,$($(PKG)_PRE_PATCH_HOOKS),$(call $(hook))$(sep))
> ? ? ? ?$(if $($(PKG)_PATCH),support/scripts/apply-patches.sh $(@D) $(DL_DIR) $($(PKG)_PATCH))
> ? ? ? ?$(Q)( \
> @@ -326,49 +341,62 @@ $(BUILD_DIR)/%/.stamp_patched:
> ? ? ? ?fi; \
> ? ? ? ?)
> ? ? ? ?$(foreach hook,$($(PKG)_POST_PATCH_HOOKS),$(call $(hook))$(sep))
> + ? ? ? $(call outputtime,$($(PKG)_NAME),patch)
> ? ? ? ?$(Q)touch $@
>
> ?# Configure
> ?$(BUILD_DIR)/%/.stamp_configured:
> + ? ? ? $(call savetime)
> ? ? ? ?$(foreach hook,$($(PKG)_PRE_CONFIGURE_HOOKS),$(call $(hook))$(sep))
> ? ? ? ?@$(call MESSAGE,"Configuring")
> ? ? ? ?$($(PKG)_CONFIGURE_CMDS)
> ? ? ? ?$(foreach hook,$($(PKG)_POST_CONFIGURE_HOOKS),$(call $(hook))$(sep))
> + ? ? ? $(call outputtime,$($(PKG)_NAME),configure)
> ? ? ? ?$(Q)touch $@
>
> ?# Build
> ?$(BUILD_DIR)/%/.stamp_built::
> ? ? ? ?@$(call MESSAGE,"Building")
> + ? ? ? $(call savetime)
> ? ? ? ?$($(PKG)_BUILD_CMDS)
> ? ? ? ?$(foreach hook,$($(PKG)_POST_BUILD_HOOKS),$(call $(hook))$(sep))
> + ? ? ? $(call outputtime,$($(PKG)_NAME),build)
> ? ? ? ?$(Q)touch $@
>
> ?# Install to host dir
> ?$(BUILD_DIR)/%/.stamp_host_installed:
> ? ? ? ?@$(call MESSAGE,"Installing to host directory")
> + ? ? ? $(call savetime)
> ? ? ? ?$($(PKG)_INSTALL_CMDS)
> ? ? ? ?$(foreach hook,$($(PKG)_POST_INSTALL_HOOKS),$(call $(hook))$(sep))
> + ? ? ? $(call outputtime,$($(PKG)_NAME),install-host)
> ? ? ? ?$(Q)touch $@
>
> ?# Install to staging dir
> ?$(BUILD_DIR)/%/.stamp_staging_installed:
> ? ? ? ?@$(call MESSAGE,"Installing to staging directory")
> + ? ? ? $(call savetime)
> ? ? ? ?$($(PKG)_INSTALL_STAGING_CMDS)
> ? ? ? ?$(foreach hook,$($(PKG)_POST_INSTALL_STAGING_HOOKS),$(call $(hook))$(sep))
> + ? ? ? $(call outputtime,$($(PKG)_NAME),install-staging)
> ? ? ? ?$(Q)touch $@
>
> ?# Install to images dir
> ?$(BUILD_DIR)/%/.stamp_images_installed:
> ? ? ? ?@$(call MESSAGE,"Installing to images directory")
> + ? ? ? $(call savetime)
> ? ? ? ?$($(PKG)_INSTALL_IMAGES_CMDS)
> ? ? ? ?$(foreach hook,$($(PKG)_POST_INSTALL_IMAGES_HOOKS),$(call $(hook))$(sep))
> + ? ? ? $(call outputtime,$($(PKG)_NAME),install-images)
> ? ? ? ?$(Q)touch $@
>
> ?# Install to target dir
> ?$(BUILD_DIR)/%/.stamp_target_installed:
> ? ? ? ?@$(call MESSAGE,"Installing to target")
> + ? ? ? $(call savetime)
> ? ? ? ?$($(PKG)_INSTALL_TARGET_CMDS)
> ? ? ? ?$(foreach hook,$($(PKG)_POST_INSTALL_TARGET_HOOKS),$(call $(hook))$(sep))
> + ? ? ? $(call outputtime,$($(PKG)_NAME),install-target)
> ? ? ? ?$(Q)touch $@
>
> ?# Clean package

Best regards,
Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [RFC] Build time graph generation
  2011-10-09 16:17 [Buildroot] [RFC] Build time graph generation Thomas Petazzoni
                   ` (2 preceding siblings ...)
  2011-10-10  9:32 ` [Buildroot] [RFC] Build time graph generation Diego Iastrubni
@ 2011-10-10 13:55 ` Thomas De Schampheleire
  2011-10-10 14:20   ` Thomas Petazzoni
  3 siblings, 1 reply; 15+ messages in thread
From: Thomas De Schampheleire @ 2011-10-10 13:55 UTC (permalink / raw)
  To: buildroot

Hi,

On Sun, Oct 9, 2011 at 6:17 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
> Hello,
>
> Here are two patches that implement a simple modification of the
> package infrastructure to output some timing data about the duration
> taken by each step for each package, and then a small Python script
> that generates graphs from those informations.
>
> I am not sure that there is any useful usage of those graphs, but it's
> fun and there are nice to look at.
>
> Here are some sample graphs, first on a moderately large package set:
>
> ?http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/histogram-build-order.pdf
> ?http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/histogram-duration-order.pdf
> ?http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/pie-packages.pdf
> ?http://free-electrons.com/~thomas/pub/buildroot/graph-time/big/pie-steps.pdf
>
> and then on a smaller package set:
>
> ?http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/histogram-build-order.pdf
> ?http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/histogram-duration-order.pdf
> ?http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/pie-packages.pdf
> ?http://free-electrons.com/~thomas/pub/buildroot/graph-time/small/pie-steps.pdf
>
> I don't think the modification to the package infrastructure is ready
> for merging (there are many cases not handled, like when the timing
> data should be cleaned up, the case of overriden packages not being
> handled, etc.) and I am not even sure it is useful to complicate the
> package infrastructure with such a not-so-useful feature.

I like the idea of having such information, so I'm in favor of these patches.

(The graphs also painfully show the time lost in all ./configure
steps, while many of the checks are identical...)

As I mentioned as comment on your patch, I think we can make this an
optional feature for those who want it.

Is it possible to have html output as an alternative to pdf? I can
also imagine that some people simply want image files, like png or
even svg, so the graphs can easily be embedded in other web pages.

Best regards,
Thomas

>
> Regards,
>
> Thomas
>
> The following changes since commit ddb8c639c312fd9f65dbb123837c100281495d50:
>
> ?libplayer: mark python bindings as broken (2011-10-08 22:39:29 +0200)
>
> are available in the git repository at:
> ?http://free-electrons.com/~thomas/buildroot.git for-2011.11/graph-build-time
>
> Thomas Petazzoni (2):
> ? ? ?package: instrument to gather timing data
> ? ? ?graph-build-time: generate graphs based on timing data
>
> ?package/Makefile.package.in ? ? ?| ? 28 ++++
> ?support/scripts/graph-build-time | ?252 ++++++++++++++++++++++++++++++++++++++
> ?2 files changed, 280 insertions(+), 0 deletions(-)
> ?create mode 100755 support/scripts/graph-build-time
>
> Thanks,
> --
> Thomas Petazzoni
> _______________________________________________
> buildroot mailing list
> buildroot at busybox.net
> http://lists.busybox.net/mailman/listinfo/buildroot
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [RFC] Build time graph generation
  2011-10-10 13:55 ` Thomas De Schampheleire
@ 2011-10-10 14:20   ` Thomas Petazzoni
  2011-10-10 15:19     ` Thomas De Schampheleire
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Petazzoni @ 2011-10-10 14:20 UTC (permalink / raw)
  To: buildroot

Thomas,

Le Mon, 10 Oct 2011 15:55:49 +0200,
Thomas De Schampheleire <patrickdepinguin+buildroot@gmail.com> a ?crit :

> > I don't think the modification to the package infrastructure is ready
> > for merging (there are many cases not handled, like when the timing
> > data should be cleaned up, the case of overriden packages not being
> > handled, etc.) and I am not even sure it is useful to complicate the
> > package infrastructure with such a not-so-useful feature.
> 
> I like the idea of having such information, so I'm in favor of these patches.

Thanks :-)

Though I'm still not sure of how they can be useful.

> (The graphs also painfully show the time lost in all ./configure
> steps, while many of the checks are identical...)

In the past, we did try to improve that situation by using the
"configure cache" mechanism, thanks to which configure checks done by
past configure script executions are used to speed up the execution of
future configure scripts (since as you say, they all do mostly the same
checks). Unfortunately, the configure scripts aren't that standardized
and they store the result of different checks in variables of the same
name, resulting to many strange problems. We had this feature enabled
by default in Buildroot for a while (even in stable releases if I'm
correct), but in the end, we dropped it because it was very complicated
to stabilized (we already had to patch multiple configure.{in,ac}
files).

> As I mentioned as comment on your patch, I think we can make this an
> optional feature for those who want it.

Yes, sure.

> Is it possible to have html output as an alternative to pdf? I can
> also imagine that some people simply want image files, like png or
> even svg, so the graphs can easily be embedded in other web pages.

Generating PNG or SVG with matplotlib is definitely possible. I'm not
sure about HTML though, do you mean a webpage that simply includes the
four graphs?

Thomas
-- 
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [RFC] Build time graph generation
  2011-10-10 14:20   ` Thomas Petazzoni
@ 2011-10-10 15:19     ` Thomas De Schampheleire
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas De Schampheleire @ 2011-10-10 15:19 UTC (permalink / raw)
  To: buildroot

On Mon, Oct 10, 2011 at 4:20 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
> Thomas,
>
> Le Mon, 10 Oct 2011 15:55:49 +0200,
> Thomas De Schampheleire <patrickdepinguin+buildroot@gmail.com> a ?crit :
>
>> > I don't think the modification to the package infrastructure is ready
>> > for merging (there are many cases not handled, like when the timing
>> > data should be cleaned up, the case of overriden packages not being
>> > handled, etc.) and I am not even sure it is useful to complicate the
>> > package infrastructure with such a not-so-useful feature.
>>
>> I like the idea of having such information, so I'm in favor of these patches.
>
> Thanks :-)
>
> Though I'm still not sure of how they can be useful.

Although I may not use it every day, I can think of the following use cases:
* compare compilation speeds between different machines
* identify disk-versus-cpu bottlenecks (e.g. if the extract takes much
longer on machine A than on B, it could be the slow harddisk of A.
This can be a trigger to use another machine or faster harddisk, or an
input to the IT department)
* better visualize the impact of enabling additional packages.
* identify sudden changes in build times, e.g. after bump from one
version to another, the build time is much bigger. If you never create
the statistics, you'll never know.

>
>> (The graphs also painfully show the time lost in all ./configure
>> steps, while many of the checks are identical...)
>
> In the past, we did try to improve that situation by using the
> "configure cache" mechanism, thanks to which configure checks done by
> past configure script executions are used to speed up the execution of
> future configure scripts (since as you say, they all do mostly the same
> checks). Unfortunately, the configure scripts aren't that standardized
> and they store the result of different checks in variables of the same
> name, resulting to many strange problems. We had this feature enabled
> by default in Buildroot for a while (even in stable releases if I'm
> correct), but in the end, we dropped it because it was very complicated
> to stabilized (we already had to patch multiple configure.{in,ac}
> files).

Ok, wasn't aware of this. Thanks for the background info.

>
>> As I mentioned as comment on your patch, I think we can make this an
>> optional feature for those who want it.
>
> Yes, sure.
>
>> Is it possible to have html output as an alternative to pdf? I can
>> also imagine that some people simply want image files, like png or
>> even svg, so the graphs can easily be embedded in other web pages.
>
> Generating PNG or SVG with matplotlib is definitely possible. I'm not
> sure about HTML though, do you mean a webpage that simply includes the
> four graphs?

Some basic page with a heading for each graph, yes. It can be as fancy
as we like, but the main advantage of such a page is that you only
have to open one thing, not four individual files...

>
> Thomas
> --
> Thomas Petazzoni, Free Electrons
> Kernel, drivers, real-time and embedded Linux
> development, consulting, training and support.
> http://free-electrons.com
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 1/2] package: instrument to gather timing data
  2011-10-10 13:41   ` Thomas De Schampheleire
@ 2011-10-11  5:59     ` Arnout Vandecappelle
  0 siblings, 0 replies; 15+ messages in thread
From: Arnout Vandecappelle @ 2011-10-11  5:59 UTC (permalink / raw)
  To: buildroot


On Monday 10 October 2011 15:41:28, Thomas De Schampheleire wrote:
> And what about making this behavior selectable, i.e. only if a certain
> config option is set, will data be gathered. In the other case,
> 'savetime' and 'outputtime' can be empty functions.

 I think the runtime overhead is minimal, so there isn't much reason to 
disable them.  And you anyway still have the $(call) overhead for each target.

 Regards,
 Arnout
-- 
Arnout Vandecappelle                               arnout at mind be
Senior Embedded Software Architect                 +32-16-286540
Essensium/Mind                                     http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium                BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  31BB CF53 8660 6F88 345D  54CC A836 5879 20D7 CF43
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.busybox.net/pipermail/buildroot/attachments/20111011/b9122932/attachment.html>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 1/2] package: instrument to gather timing data
  2011-10-09 16:17 ` [Buildroot] [PATCH 1/2] package: instrument to gather timing data Thomas Petazzoni
  2011-10-10 13:41   ` Thomas De Schampheleire
@ 2011-10-11  5:59   ` Arnout Vandecappelle
  2011-10-11  7:34     ` Thomas Petazzoni
  2011-10-11  8:29     ` Thomas De Schampheleire
  1 sibling, 2 replies; 15+ messages in thread
From: Arnout Vandecappelle @ 2011-10-11  5:59 UTC (permalink / raw)
  To: buildroot



On Sunday 09 October 2011 18:17:27, Thomas Petazzoni wrote:
> Instrument the package infrastructure to generate a
> $(O)/build-time.data file which contains one line for each step of
> each package and the corresponding duration in milliseconds.
> 
> The instrumentation is not perfect yet, as it doesn't account for
> packages with overriden source directory 



 Why is that relevant?  The output goes to $(O) anyway.  But this makes me 
think: wouldn't it be better to 



> and the build-time.data is
> never removed, so results will accumulate if several partial builds
> are done.



 I would call that a feature :-)  Partial builds typically mean that you're 
hacking away at some package, and then it's very relevant to see the impact on 
build time.



 Of course, there would need to be a target buildtime-clean that removes the 
files.



> 
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
>  package/Makefile.package.in |   28 ++++++++++++++++++++++++++++
>  1 files changed, 28 insertions(+), 0 deletions(-)
> 
> diff --git a/package/Makefile.package.in b/package/Makefile.package.in
> index b5ef57b..605b518 100644
> --- a/package/Makefile.package.in
> +++ b/package/Makefile.package.in
> @@ -254,6 +254,18 @@ define sep
> 
>  endef
> 
> +define savetime
> +       echo $$(($$(date +%s%N)/1000000)) > $(O)/.br.time
> +endef
> +
> +define outputtime
> +       newtime=`echo $$(($$(date +%s%N)/1000000))` ; \
> +       oldtime=`cat $(O)/.br.time` ; \
> +       rm -f .br.time	      ; \
> +       timediff=$$(($$newtime-$$oldtime)) ; \
> +       echo "$(1),$(2),$$timediff" >> $(O)/build-time.data



 Is there a particular reason to use a make function parameter in a place like 
this instead of using $($(PKG)_NAME) directly?  I've seen this in other places 
in buildroot as well...



[snip]



 Regards,
 Arnout
-- 
Arnout Vandecappelle                               arnout at mind be
Senior Embedded Software Architect                 +32-16-286540
Essensium/Mind                                     http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium                BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  31BB CF53 8660 6F88 345D  54CC A836 5879 20D7 CF43


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.busybox.net/pipermail/buildroot/attachments/20111011/018079a2/attachment-0001.html>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 1/2] package: instrument to gather timing data
  2011-10-11  5:59   ` Arnout Vandecappelle
@ 2011-10-11  7:34     ` Thomas Petazzoni
  2011-10-11  8:29     ` Thomas De Schampheleire
  1 sibling, 0 replies; 15+ messages in thread
From: Thomas Petazzoni @ 2011-10-11  7:34 UTC (permalink / raw)
  To: buildroot

Le Tue, 11 Oct 2011 07:59:22 +0200,
Arnout Vandecappelle <arnout@mind.be> a ?crit :

> On Sunday 09 October 2011 18:17:27, Thomas Petazzoni wrote:
> > Instrument the package infrastructure to generate a
> > $(O)/build-time.data file which contains one line for each step of
> > each package and the corresponding duration in milliseconds.
> > 
> > The instrumentation is not perfect yet, as it doesn't account for
> > packages with overriden source directory 
> 
>  Why is that relevant?

With an overidden source directory, the step of steps are different:
instead of download, extract, patch, configure, etc., it's rsync,
configure, etc.

>  The output goes to $(O) anyway.  But this makes me 
> think: wouldn't it be better to 

To ? :-)

>  I would call that a feature :-)  Partial builds typically mean that you're 
> hacking away at some package, and then it's very relevant to see the impact on 
> build time.

Ok.

>  Of course, there would need to be a target buildtime-clean that removes the 
> files.

Why not, yes.

> > +define outputtime
> > +       newtime=`echo $$(($$(date +%s%N)/1000000))` ; \
> > +       oldtime=`cat $(O)/.br.time` ; \
> > +       rm -f .br.time	      ; \
> > +       timediff=$$(($$newtime-$$oldtime)) ; \
> > +       echo "$(1),$(2),$$timediff" >> $(O)/build-time.data
> 
>  Is there a particular reason to use a make function parameter in a place like 
> this instead of using $($(PKG)_NAME) directly?  I've seen this in other places 
> in buildroot as well...

No, I guess I could use $($(PKG)_NAME) directly.

Regards,

Thomas
-- 
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 1/2] package: instrument to gather timing data
  2011-10-11  5:59   ` Arnout Vandecappelle
  2011-10-11  7:34     ` Thomas Petazzoni
@ 2011-10-11  8:29     ` Thomas De Schampheleire
  2011-10-11 16:12       ` Arnout Vandecappelle
  1 sibling, 1 reply; 15+ messages in thread
From: Thomas De Schampheleire @ 2011-10-11  8:29 UTC (permalink / raw)
  To: buildroot

Hi,

On Tue, Oct 11, 2011 at 7:59 AM, Arnout Vandecappelle <arnout@mind.be> wrote:
>
> On Sunday 09 October 2011 18:17:27, Thomas Petazzoni wrote:
>
>> Instrument the package infrastructure to generate a
>
>> $(O)/build-time.data file which contains one line for each step of
>
>> each package and the corresponding duration in milliseconds.
>
>>
>
>> The instrumentation is not perfect yet, as it doesn't account for
>
>> packages with overriden source directory
>
> Why is that relevant? The output goes to $(O) anyway. But this makes me
> think: wouldn't it be better to
>
>> and the build-time.data is
>
>> never removed, so results will accumulate if several partial builds
>
>> are done.
>
> I would call that a feature :-) Partial builds typically mean that you're
> hacking away at some package, and then it's very relevant to see the impact
> on build time.

How would you see the impact? Wouldn't it be more useful to save the
timing data for subsequent runs in different files (e.g. timestamped
files) so that you can compare such runs?
If you let the data accumulate, you'd get one big number for each
step/package combination, unless you're going to update the parser
script to display the different data lines as separate entities, one
for each run).

>
> Of course, there would need to be a target buildtime-clean that removes the
> files.
>
>>
>
>> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
>
>> ---
>
>> package/Makefile.package.in | 28 ++++++++++++++++++++++++++++
>
>> 1 files changed, 28 insertions(+), 0 deletions(-)
>
>>
>
>> diff --git a/package/Makefile.package.in b/package/Makefile.package.in
>
>> index b5ef57b..605b518 100644
>
>> --- a/package/Makefile.package.in
>
>> +++ b/package/Makefile.package.in
>
>> @@ -254,6 +254,18 @@ define sep
>
>>
>
>> endef
>
>>
>
>> +define savetime
>
>> + echo $$(($$(date +%s%N)/1000000)) > $(O)/.br.time
>
>> +endef
>
>> +
>
>> +define outputtime
>
>> + newtime=`echo $$(($$(date +%s%N)/1000000))` ; \
>
>> + oldtime=`cat $(O)/.br.time` ; \
>
>> + rm -f .br.time ; \
>
>> + timediff=$$(($$newtime-$$oldtime)) ; \
>
>> + echo "$(1),$(2),$$timediff" >> $(O)/build-time.data
>
> Is there a particular reason to use a make function parameter in a place
> like this instead of using $($(PKG)_NAME) directly? I've seen this in other
> places in buildroot as well...
>
> [snip]
>
> Regards,
>
> Arnout
>
> --
>
> Arnout Vandecappelle arnout at mind be
>
> Senior Embedded Software Architect +32-16-286540
>
> Essensium/Mind http://www.mind.be
>
> G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven
>
> LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
>
> GPG fingerprint: 31BB CF53 8660 6F88 345D 54CC A836 5879 20D7 CF43
>
>
> _______________________________________________
> buildroot mailing list
> buildroot at busybox.net
> http://lists.busybox.net/mailman/listinfo/buildroot
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 1/2] package: instrument to gather timing data
  2011-10-11  8:29     ` Thomas De Schampheleire
@ 2011-10-11 16:12       ` Arnout Vandecappelle
  2011-10-11 18:17         ` Thomas Petazzoni
  0 siblings, 1 reply; 15+ messages in thread
From: Arnout Vandecappelle @ 2011-10-11 16:12 UTC (permalink / raw)
  To: buildroot


On Tuesday 11 October 2011 10:29:13, Thomas De Schampheleire wrote:
> >> and the build-time.data is
> >> never removed, so results will accumulate if several partial builds
> >> are done.
> > 
> > I would call that a feature :-) Partial builds typically mean that you're
> > hacking away at some package, and then it's very relevant to see the
> > impact on build time.
> 
> How would you see the impact? Wouldn't it be more useful to save the
> timing data for subsequent runs in different files (e.g. timestamped
> files) so that you can compare such runs?
> If you let the data accumulate, you'd get one big number for each
> step/package combination, unless you're going to update the parser
> script to display the different data lines as separate entities, one
> for each run).

 I hadn't read the parser script, I assumed it would just generate a different 
bar for each run.  Now I see it would only work in pie-steps mode.

 BTW, histogram is a wrong name.  A histogram would for instance indicate how 
many packages have a build time between 1 and 2 seconds.

 Regards,
 Arnout

-- 
Arnout Vandecappelle                               arnout at mind be
Senior Embedded Software Architect                 +32-16-286540
Essensium/Mind                                     http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium                BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  31BB CF53 8660 6F88 345D  54CC A836 5879 20D7 CF43
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.busybox.net/pipermail/buildroot/attachments/20111011/6c5aa6d8/attachment.html>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Buildroot] [PATCH 1/2] package: instrument to gather timing data
  2011-10-11 16:12       ` Arnout Vandecappelle
@ 2011-10-11 18:17         ` Thomas Petazzoni
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Petazzoni @ 2011-10-11 18:17 UTC (permalink / raw)
  To: buildroot

Le Tue, 11 Oct 2011 18:12:06 +0200,
Arnout Vandecappelle <arnout@mind.be> a ?crit :

>  BTW, histogram is a wrong name.  A histogram would for instance
> indicate how many packages have a build time between 1 and 2 seconds.

Yeah, bargraph would probably be more correct. My statistics-foo is
really terrible, I apologize.

Thomas
-- 
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2011-10-11 18:17 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-09 16:17 [Buildroot] [RFC] Build time graph generation Thomas Petazzoni
2011-10-09 16:17 ` [Buildroot] [PATCH 1/2] package: instrument to gather timing data Thomas Petazzoni
2011-10-10 13:41   ` Thomas De Schampheleire
2011-10-11  5:59     ` Arnout Vandecappelle
2011-10-11  5:59   ` Arnout Vandecappelle
2011-10-11  7:34     ` Thomas Petazzoni
2011-10-11  8:29     ` Thomas De Schampheleire
2011-10-11 16:12       ` Arnout Vandecappelle
2011-10-11 18:17         ` Thomas Petazzoni
2011-10-09 16:17 ` [Buildroot] [PATCH 2/2] graph-build-time: generate graphs based on " Thomas Petazzoni
2011-10-10 13:12   ` Thomas De Schampheleire
2011-10-10  9:32 ` [Buildroot] [RFC] Build time graph generation Diego Iastrubni
2011-10-10 13:55 ` Thomas De Schampheleire
2011-10-10 14:20   ` Thomas Petazzoni
2011-10-10 15:19     ` Thomas De Schampheleire

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox