summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorRoss Burton <ross.burton@arm.com>2023-03-21 17:39:43 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-03-23 22:36:46 +0000
commit1908193b81a1a5dbe04ccf296c2daa15bfac7000 (patch)
treed6dd1b64954e04629cc5b0b602a9cb42905443ed /scripts
parentab7a9262a5616b299579c686428da028f72250a2 (diff)
downloadpoky-1908193b81a1a5dbe04ccf296c2daa15bfac7000.tar.gz
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>
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/buildstats-summary126
1 files changed, 126 insertions, 0 deletions
diff --git a/scripts/buildstats-summary b/scripts/buildstats-summary
new file mode 100755
index 0000000000..89348318af
--- /dev/null
+++ b/scripts/buildstats-summary
@@ -0,0 +1,126 @@
1#! /usr/bin/python3
2#
3# Dump a summary of the specified buildstats to the terminal, filtering and
4# sorting by walltime.
5#
6# SPDX-License-Identifier: GPL-2.0-only
7
8import argparse
9import dataclasses
10import datetime
11import enum
12import os
13import pathlib
14import sys
15
16scripts_path = os.path.dirname(os.path.realpath(__file__))
17sys.path.append(os.path.join(scripts_path, "lib"))
18import buildstats
19
20
21@dataclasses.dataclass
22class Task:
23 recipe: str
24 task: str
25 start: datetime.datetime
26 duration: datetime.timedelta
27
28
29class Sorting(enum.Enum):
30 start = 1
31 duration = 2
32
33 # argparse integration
34 def __str__(self) -> str:
35 return self.name
36
37 def __repr__(self) -> str:
38 return self.name
39
40 @staticmethod
41 def from_string(s: str):
42 try:
43 return Sorting[s]
44 except KeyError:
45 return s
46
47
48def read_buildstats(path: pathlib.Path) -> buildstats.BuildStats:
49 if not path.exists():
50 raise Exception(f"No such file or directory: {path}")
51 if path.is_file():
52 return buildstats.BuildStats.from_file_json(path)
53 if (path / "build_stats").is_file():
54 return buildstats.BuildStats.from_dir(path)
55 raise Exception(f"Cannot find buildstats in {path}")
56
57
58def dump_buildstats(args, bs: buildstats.BuildStats):
59 tasks = []
60 for recipe in bs.values():
61 for task, stats in recipe.tasks.items():
62 t = Task(
63 recipe.name,
64 task,
65 datetime.datetime.fromtimestamp(stats["start_time"]),
66 datetime.timedelta(seconds=int(stats.walltime)),
67 )
68 tasks.append(t)
69
70 tasks.sort(key=lambda t: getattr(t, args.sort.name))
71
72 minimum = datetime.timedelta(seconds=args.shortest)
73 highlight = datetime.timedelta(seconds=args.highlight)
74
75 for t in tasks:
76 if t.duration >= minimum:
77 line = f"{t.duration} {t.recipe}:{t.task}"
78 if t.duration >= highlight:
79 print(f"\033[1m{line}\033[0m")
80 else:
81 print(line)
82
83
84def main(argv=None) -> int:
85 parser = argparse.ArgumentParser(
86 formatter_class=argparse.ArgumentDefaultsHelpFormatter
87 )
88
89 parser.add_argument(
90 "buildstats", metavar="BUILDSTATS", help="Buildstats file", type=pathlib.Path
91 )
92 parser.add_argument(
93 "--sort",
94 "-s",
95 type=Sorting.from_string,
96 choices=list(Sorting),
97 default=Sorting.start,
98 help="Sort tasks",
99 )
100 parser.add_argument(
101 "--shortest",
102 "-t",
103 type=int,
104 default=1,
105 metavar="SECS",
106 help="Hide tasks shorter than SECS seconds",
107 )
108 parser.add_argument(
109 "--highlight",
110 "-g",
111 type=int,
112 default=60,
113 metavar="SECS",
114 help="Highlight tasks longer than SECS seconds",
115 )
116
117 args = parser.parse_args(argv)
118
119 bs = read_buildstats(args.buildstats)
120 dump_buildstats(args, bs)
121
122 return 0
123
124
125if __name__ == "__main__":
126 sys.exit(main())