poky/scripts/buildstats-summary
Ross Burton 1908193b81 scripts: add buildstats-summary
This script will write a summary of the buildstats to the terminal,
sorted by start time or duration, optionally hiding short tasks, and
highlighting long running tasks.

(From OE-Core rev: 253d2c0eb048ea38822844ebb69ad76d55b5c3ef)

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2023-03-23 22:36:46 +00:00

3.0 KiB
Executable File

#! /usr/bin/python3

Dump a summary of the specified buildstats to the terminal, filtering and

sorting by walltime.

SPDX-License-Identifier: GPL-2.0-only

import argparse import dataclasses import datetime import enum import os import pathlib import sys

scripts_path = os.path.dirname(os.path.realpath(file)) sys.path.append(os.path.join(scripts_path, "lib")) import buildstats

@dataclasses.dataclass class Task: recipe: str task: str start: datetime.datetime duration: datetime.timedelta

class Sorting(enum.Enum): start = 1 duration = 2

# argparse integration
def __str__(self) -> str:
    return self.name

def __repr__(self) -> str:
    return self.name

@staticmethod
def from_string(s: str):
    try:
        return Sorting[s]
    except KeyError:
        return s

def read_buildstats(path: pathlib.Path) -> buildstats.BuildStats: if not path.exists(): raise Exception(f"No such file or directory: {path}") if path.is_file(): return buildstats.BuildStats.from_file_json(path) if (path / "build_stats").is_file(): return buildstats.BuildStats.from_dir(path) raise Exception(f"Cannot find buildstats in {path}")

def dump_buildstats(args, bs: buildstats.BuildStats): tasks = [] for recipe in bs.values(): for task, stats in recipe.tasks.items(): t = Task( recipe.name, task, datetime.datetime.fromtimestamp(stats["start_time"]), datetime.timedelta(seconds=int(stats.walltime)), ) tasks.append(t)

tasks.sort(key=lambda t: getattr(t, args.sort.name))

minimum = datetime.timedelta(seconds=args.shortest)
highlight = datetime.timedelta(seconds=args.highlight)

for t in tasks:
    if t.duration >= minimum:
        line = f"{t.duration}    {t.recipe}:{t.task}"
        if t.duration >= highlight:
            print(f"\033[1m{line}\033[0m")
        else:
            print(line)

def main(argv=None) -> int: parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter )

parser.add_argument(
    "buildstats", metavar="BUILDSTATS", help="Buildstats file", type=pathlib.Path
)
parser.add_argument(
    "--sort",
    "-s",
    type=Sorting.from_string,
    choices=list(Sorting),
    default=Sorting.start,
    help="Sort tasks",
)
parser.add_argument(
    "--shortest",
    "-t",
    type=int,
    default=1,
    metavar="SECS",
    help="Hide tasks shorter than SECS seconds",
)
parser.add_argument(
    "--highlight",
    "-g",
    type=int,
    default=60,
    metavar="SECS",
    help="Highlight tasks longer than SECS seconds",
)

args = parser.parse_args(argv)

bs = read_buildstats(args.buildstats)
dump_buildstats(args, bs)

return 0

if name == "main": sys.exit(main())