Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/476309/?format=api
{ "id": 476309, "url": "http://patchwork.ozlabs.org/api/patches/476309/?format=api", "web_url": "http://patchwork.ozlabs.org/project/buildroot/patch/1432591007-27689-3-git-send-email-thomas.petazzoni@free-electrons.com/", "project": { "id": 27, "url": "http://patchwork.ozlabs.org/api/projects/27/?format=api", "name": "Buildroot development", "link_name": "buildroot", "list_id": "buildroot.buildroot.org", "list_email": "buildroot@buildroot.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1432591007-27689-3-git-send-email-thomas.petazzoni@free-electrons.com>", "list_archive_url": null, "date": "2015-05-25T21:56:45", "name": "[v4,2015.08,2/4] support/scripts: add size-stats script", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "b5d00dcfeea35e5405d90f9cf92c94a644cf0dde", "submitter": { "id": 2230, "url": "http://patchwork.ozlabs.org/api/people/2230/?format=api", "name": "Thomas Petazzoni", "email": "thomas.petazzoni@free-electrons.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/buildroot/patch/1432591007-27689-3-git-send-email-thomas.petazzoni@free-electrons.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/476309/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/476309/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<buildroot-bounces@busybox.net>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "buildroot@lists.busybox.net" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "buildroot@osuosl.org" ], "Received": [ "from whitealder.osuosl.org (whitealder.osuosl.org\n\t[140.211.166.138])\n\tby ozlabs.org (Postfix) with ESMTP id 84D1A1402B5\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 26 May 2015 07:57:19 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id AD7AE91556;\n\tMon, 25 May 2015 21:57:18 +0000 (UTC)", "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id jQ-jwmWN6AJt; Mon, 25 May 2015 21:57:10 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 63B2991592;\n\tMon, 25 May 2015 21:57:00 +0000 (UTC)", "from whitealder.osuosl.org (whitealder.osuosl.org\n\t[140.211.166.138])\n\tby ash.osuosl.org (Postfix) with ESMTP id 636141BFA9E\n\tfor <buildroot@lists.busybox.net>;\n\tMon, 25 May 2015 21:56:54 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 4A7BF91556\n\tfor <buildroot@lists.busybox.net>;\n\tMon, 25 May 2015 21:56:54 +0000 (UTC)", "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id yA8sDNGsX34T for <buildroot@lists.busybox.net>;\n\tMon, 25 May 2015 21:56:52 +0000 (UTC)", "from mail.free-electrons.com (down.free-electrons.com\n\t[37.187.137.238])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id CE7AA91536\n\tfor <buildroot@uclibc.org>; Mon, 25 May 2015 21:56:51 +0000 (UTC)", "by mail.free-electrons.com (Postfix, from userid 106)\n\tid 74A18809; Mon, 25 May 2015 23:56:51 +0200 (CEST)", "from localhost (AToulouse-657-1-1132-11.w92-156.abo.wanadoo.fr\n\t[92.156.54.11])\n\tby mail.free-electrons.com (Postfix) with ESMTPSA id 33871279;\n\tMon, 25 May 2015 23:56:51 +0200 (CEST)" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "From": "Thomas Petazzoni <thomas.petazzoni@free-electrons.com>", "To": "buildroot@uclibc.org", "Date": "Mon, 25 May 2015 23:56:45 +0200", "Message-Id": "<1432591007-27689-3-git-send-email-thomas.petazzoni@free-electrons.com>", "X-Mailer": "git-send-email 2.1.0", "In-Reply-To": "<1432591007-27689-1-git-send-email-thomas.petazzoni@free-electrons.com>", "References": "<1432591007-27689-1-git-send-email-thomas.petazzoni@free-electrons.com>", "Cc": "Thomas Petazzoni <thomas.petazzoni@free-electrons.com>", "Subject": "[Buildroot] [PATCH v4 2015.08 2/4] support/scripts: add size-stats\n\tscript", "X-BeenThere": "buildroot@busybox.net", "X-Mailman-Version": "2.1.18-1", "Precedence": "list", "List-Id": "Discussion and development of buildroot <buildroot.busybox.net>", "List-Unsubscribe": "<http://lists.busybox.net/mailman/options/buildroot>,\n\t<mailto:buildroot-request@busybox.net?subject=unsubscribe>", "List-Archive": "<http://lists.busybox.net/pipermail/buildroot/>", "List-Post": "<mailto:buildroot@busybox.net>", "List-Help": "<mailto:buildroot-request@busybox.net?subject=help>", "List-Subscribe": "<http://lists.busybox.net/mailman/listinfo/buildroot>,\n\t<mailto:buildroot-request@busybox.net?subject=subscribe>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "buildroot-bounces@busybox.net", "Sender": "\"buildroot\" <buildroot-bounces@busybox.net>" }, "content": "This new script uses the data collected by the step_pkg_size\ninstrumentation hook to generate a pie chart of the size contribution\nof each package to the target root filesystem, and two CSV files with\nstatistics about the package size and file size. To achieve this, it\nlooks at each file in $(TARGET_DIR), and using the\npackages-file-list.txt information collected by the step_pkg_size\nhook, it determines to which package the file belongs. It is therefore\nable to give the size installed by each package.\n\nSigned-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>\n---\n support/scripts/size-stats | 238 +++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 238 insertions(+)\n create mode 100755 support/scripts/size-stats", "diff": "diff --git a/support/scripts/size-stats b/support/scripts/size-stats\nnew file mode 100755\nindex 0000000..48a64cd\n--- /dev/null\n+++ b/support/scripts/size-stats\n@@ -0,0 +1,238 @@\n+#!/usr/bin/env python\n+\n+# Copyright (C) 2014 by Thomas Petazzoni <thomas.petazzoni@free-electrons.com>\n+\n+# This program is free software; you can redistribute it and/or modify\n+# it under the terms of the GNU General Public License as published by\n+# the Free Software Foundation; either version 2 of the License, or\n+# (at your option) any later version.\n+#\n+# This program is distributed in the hope that it will be useful,\n+# but WITHOUT ANY WARRANTY; without even the implied warranty of\n+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n+# General Public License for more details.\n+#\n+# You should have received a copy of the GNU General Public License\n+# along with this program; if not, write to the Free Software\n+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n+\n+import sys\n+import os\n+import os.path\n+import argparse\n+import csv\n+import collections\n+\n+try:\n+ import matplotlib.font_manager as fm\n+ import matplotlib.pyplot as plt\n+except ImportError:\n+ sys.stderr.write(\"You need python-matplotlib to generate the size graph\\n\")\n+ exit(1)\n+\n+colors = ['#e60004', '#009836', '#2e1d86', '#ffed00',\n+ '#0068b5', '#f28e00', '#940084', '#97c000']\n+\n+#\n+# This function adds a new file to 'filesdict', after checking its\n+# size. The 'filesdict' contain the relative path of the file as the\n+# key, and as the value a tuple containing the name of the package to\n+# which the file belongs and the size of the file.\n+#\n+# filesdict: the dict to which the file is added\n+# relpath: relative path of the file\n+# fullpath: absolute path to the file\n+# pkg: package to which the file belongs\n+#\n+def add_file(filesdict, relpath, abspath, pkg):\n+ if not os.path.exists(abspath):\n+ return\n+ if os.path.islink(abspath):\n+ return\n+ sz = os.stat(abspath).st_size\n+ filesdict[relpath] = (pkg, sz)\n+\n+#\n+# This function returns a dict containing as keys the files present in\n+# the filesystem skeleton, and as value, the string \"skeleton\". It is\n+# used to simulate a fake \"skeleton\" package, to assign the files from\n+# the skeleton to some package.\n+#\n+# builddir: path to the Buildroot output directory\n+# skeleton_path: path to the rootfs skeleton\n+#\n+def build_skeleton_dict(builddir, skeleton_path):\n+ skeleton_files = {}\n+ for root, _, files in os.walk(skeleton_path):\n+ for f in files:\n+ if f == \".empty\":\n+ continue\n+ frelpath = os.path.relpath(os.path.join(root, f), skeleton_path)\n+ # Get the real size of the installed file\n+ targetpath = os.path.join(builddir, \"target\", frelpath)\n+ add_file(skeleton_files, frelpath, targetpath, \"skeleton\")\n+ return skeleton_files\n+\n+#\n+# This function returns a dict where each key is the path of a file in\n+# the root filesystem, and the value is a tuple containing two\n+# elements: the name of the package to which this file belongs and the\n+# size of the file.\n+#\n+# builddir: path to the Buildroot output directory\n+#\n+def build_package_dict(builddir):\n+ filesdict = {}\n+ with open(os.path.join(builddir, \"build\", \"packages-file-list.txt\")) as filelistf:\n+ for l in filelistf.readlines():\n+ pkg, fpath = l.split(\",\")\n+ # remove the initial './' in each file path\n+ fpath = fpath.strip()[2:]\n+ fullpath = os.path.join(builddir, \"target\", fpath)\n+ add_file(filesdict, fpath, fullpath, pkg)\n+ return filesdict\n+\n+#\n+# This function builds a dictionary that contains the name of a\n+# package as key, and the size of the files installed by this package\n+# as the value.\n+#\n+# filesdict: dictionary with the name of the files as key, and as\n+# value a tuple containing the name of the package to which the files\n+# belongs, and the size of the file. As returned by\n+# build_package_dict.\n+#\n+# builddir: path to the Buildroot output directory\n+#\n+def build_package_size(filesdict, builddir):\n+ pkgsize = collections.defaultdict(int)\n+\n+ for root, _, files in os.walk(os.path.join(builddir, \"target\")):\n+ for f in files:\n+ fpath = os.path.join(root, f)\n+ if os.path.islink(fpath):\n+ continue\n+ frelpath = os.path.relpath(fpath, os.path.join(builddir, \"target\"))\n+ if not frelpath in filesdict:\n+ print(\"WARNING: %s is not part of any package\" % frelpath)\n+ pkg = \"unknown\"\n+ else:\n+ pkg = filesdict[frelpath][0]\n+\n+ pkgsize[pkg] += os.path.getsize(fpath)\n+\n+ return pkgsize\n+\n+#\n+# Given a dict returned by build_package_size(), this function\n+# generates a pie chart of the size installed by each package.\n+#\n+# pkgsize: dictionary with the name of the package as a key, and the\n+# size as the value, as returned by build_package_size.\n+#\n+# outputf: output file for the graph\n+#\n+def draw_graph(pkgsize, outputf):\n+ total = sum(pkgsize.values())\n+ labels = []\n+ values = []\n+ other_value = 0\n+ for (p, sz) in pkgsize.items():\n+ if sz < (total * 0.01):\n+ other_value += sz\n+ else:\n+ labels.append(\"%s (%d kB)\" % (p, sz / 1000.))\n+ values.append(sz)\n+ labels.append(\"Other (%d kB)\" % (other_value / 1000.))\n+ values.append(other_value)\n+\n+ plt.figure()\n+ patches, texts, autotexts = plt.pie(values, labels=labels,\n+ autopct='%1.1f%%', shadow=True,\n+ colors=colors)\n+ # Reduce text size\n+ proptease = fm.FontProperties()\n+ proptease.set_size('xx-small')\n+ plt.setp(autotexts, fontproperties=proptease)\n+ plt.setp(texts, fontproperties=proptease)\n+\n+ plt.title('Size per package')\n+ plt.savefig(outputf)\n+\n+#\n+# Generate a CSV file with statistics about the size of each file, its\n+# size contribution to the package and to the overall system.\n+#\n+# filesdict: dictionary with the name of the files as key, and as\n+# value a tuple containing the name of the package to which the files\n+# belongs, and the size of the file. As returned by\n+# build_package_dict.\n+#\n+# pkgsize: dictionary with the name of the package as a key, and the\n+# size as the value, as returned by build_package_size.\n+#\n+# outputf: output CSV file\n+#\n+def gen_files_csv(filesdict, pkgsizes, outputf):\n+ total = 0\n+ for (p, sz) in pkgsizes.items():\n+ total += sz\n+ with open(outputf, 'w') as csvfile:\n+ wr = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)\n+ wr.writerow([\"File name\",\n+ \"Package name\",\n+ \"File size\",\n+ \"Package size\",\n+ \"File size in package (%)\",\n+ \"File size in system (%)\"])\n+ for f, (pkgname, filesize) in filesdict.items():\n+ pkgsize = pkgsizes[pkgname]\n+ wr.writerow([f, pkgname, filesize, pkgsize,\n+ \"%.1f\" % (float(filesize) / pkgsize * 100),\n+ \"%.1f\" % (float(filesize) / total * 100)])\n+\n+\n+#\n+# Generate a CSV file with statistics about the size of each package,\n+# and their size contribution to the overall system.\n+#\n+# pkgsize: dictionary with the name of the package as a key, and the\n+# size as the value, as returned by build_package_size.\n+#\n+# outputf: output CSV file\n+#\n+def gen_packages_csv(pkgsizes, outputf):\n+ total = sum(pkgsizes.values())\n+ with open(outputf, 'w') as csvfile:\n+ wr = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)\n+ wr.writerow([\"Package name\", \"Package size\", \"Package size in system (%)\"])\n+ for (pkg, size) in pkgsizes.items():\n+ wr.writerow([pkg, size, \"%.1f\" % (float(size) / total * 100)])\n+\n+parser = argparse.ArgumentParser(description='Draw build time graphs')\n+\n+parser.add_argument(\"--builddir\", '-i', metavar=\"BUILDDIR\", required=True,\n+ help=\"Buildroot output directory\")\n+parser.add_argument(\"--graph\", '-g', metavar=\"GRAPH\",\n+ help=\"Graph output file (.pdf or .png extension)\")\n+parser.add_argument(\"--file-size-csv\", '-f', metavar=\"FILE_SIZE_CSV\",\n+ help=\"CSV output file with file size statistics\")\n+parser.add_argument(\"--package-size-csv\", '-p', metavar=\"PKG_SIZE_CSV\",\n+ help=\"CSV output file with package size statistics\")\n+parser.add_argument(\"--skeleton-path\", '-s', metavar=\"SKELETON_PATH\", required=True,\n+ help=\"Path to the skeleton used for the system\")\n+args = parser.parse_args()\n+\n+# Find out which package installed what files\n+pkgdict = build_package_dict(args.builddir)\n+pkgdict.update(build_skeleton_dict(args.builddir, args.skeleton_path))\n+\n+# Collect the size installed by each package\n+pkgsize = build_package_size(pkgdict, args.builddir)\n+\n+if args.graph:\n+ draw_graph(pkgsize, args.graph)\n+if args.file_size_csv:\n+ gen_files_csv(pkgdict, pkgsize, args.file_size_csv)\n+if args.package_size_csv:\n+ gen_packages_csv(pkgsize, args.package_size_csv)\n", "prefixes": [ "v4", "2015.08", "2/4" ] }