diff options
author | Ross Burton <ross.burton@arm.com> | 2023-02-14 16:46:14 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-02-17 18:01:01 +0000 |
commit | 163aa6f1490b00d36c42611c77fc61b71ced601d (patch) | |
tree | b821a0057d100ed44389dca55734b3168d77564d /scripts | |
parent | 6807f364470b63370524d1966a8973ad56f163ee (diff) | |
download | poky-163aa6f1490b00d36c42611c77fc61b71ced601d.tar.gz |
lib/buildstats: handle tasks that never finished
If a task is aborted the buildstats file isn't complete, so calculate
when the build finished and use that as a end time.
(From OE-Core rev: 23ebaec476dc46aebe5997f025661137f3e341bd)
Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/lib/buildstats.py | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/scripts/lib/buildstats.py b/scripts/lib/buildstats.py index 3b76286ba5..fa94c65539 100644 --- a/scripts/lib/buildstats.py +++ b/scripts/lib/buildstats.py | |||
@@ -79,8 +79,8 @@ class BSTask(dict): | |||
79 | return self['rusage']['ru_oublock'] | 79 | return self['rusage']['ru_oublock'] |
80 | 80 | ||
81 | @classmethod | 81 | @classmethod |
82 | def from_file(cls, buildstat_file): | 82 | def from_file(cls, buildstat_file, fallback_end=0): |
83 | """Read buildstat text file""" | 83 | """Read buildstat text file. fallback_end is an optional end time for tasks that are not recorded as finishing.""" |
84 | bs_task = cls() | 84 | bs_task = cls() |
85 | log.debug("Reading task buildstats from %s", buildstat_file) | 85 | log.debug("Reading task buildstats from %s", buildstat_file) |
86 | end_time = None | 86 | end_time = None |
@@ -108,7 +108,10 @@ class BSTask(dict): | |||
108 | bs_task[ru_type][ru_key] = val | 108 | bs_task[ru_type][ru_key] = val |
109 | elif key == 'Status': | 109 | elif key == 'Status': |
110 | bs_task['status'] = val | 110 | bs_task['status'] = val |
111 | if end_time is not None and start_time is not None: | 111 | # If the task didn't finish, fill in the fallback end time if specified |
112 | if start_time and not end_time and fallback_end: | ||
113 | end_time = fallback_end | ||
114 | if start_time and end_time: | ||
112 | bs_task['elapsed_time'] = end_time - start_time | 115 | bs_task['elapsed_time'] = end_time - start_time |
113 | else: | 116 | else: |
114 | raise BSError("{} looks like a invalid buildstats file".format(buildstat_file)) | 117 | raise BSError("{} looks like a invalid buildstats file".format(buildstat_file)) |
@@ -226,15 +229,33 @@ class BuildStats(dict): | |||
226 | epoch = match.group('epoch') | 229 | epoch = match.group('epoch') |
227 | return name, epoch, version, revision | 230 | return name, epoch, version, revision |
228 | 231 | ||
232 | @staticmethod | ||
233 | def parse_top_build_stats(path): | ||
234 | """ | ||
235 | Parse the top-level build_stats file for build-wide start and duration. | ||
236 | """ | ||
237 | with open(path) as fobj: | ||
238 | for line in fobj.readlines(): | ||
239 | key, val = line.split(':', 1) | ||
240 | val = val.strip() | ||
241 | if key == 'Build Started': | ||
242 | start = float(val) | ||
243 | elif key == "Elapsed time": | ||
244 | elapsed = float(val.split()[0]) | ||
245 | return start, elapsed | ||
246 | |||
229 | @classmethod | 247 | @classmethod |
230 | def from_dir(cls, path): | 248 | def from_dir(cls, path): |
231 | """Load buildstats from a buildstats directory""" | 249 | """Load buildstats from a buildstats directory""" |
232 | if not os.path.isfile(os.path.join(path, 'build_stats')): | 250 | top_stats = os.path.join(path, 'build_stats') |
251 | if not os.path.isfile(top_stats): | ||
233 | raise BSError("{} does not look like a buildstats directory".format(path)) | 252 | raise BSError("{} does not look like a buildstats directory".format(path)) |
234 | 253 | ||
235 | log.debug("Reading buildstats directory %s", path) | 254 | log.debug("Reading buildstats directory %s", path) |
236 | |||
237 | buildstats = cls() | 255 | buildstats = cls() |
256 | build_started, build_elapsed = buildstats.parse_top_build_stats(top_stats) | ||
257 | build_end = build_started + build_elapsed | ||
258 | |||
238 | subdirs = os.listdir(path) | 259 | subdirs = os.listdir(path) |
239 | for dirname in subdirs: | 260 | for dirname in subdirs: |
240 | recipe_dir = os.path.join(path, dirname) | 261 | recipe_dir = os.path.join(path, dirname) |
@@ -244,7 +265,7 @@ class BuildStats(dict): | |||
244 | bsrecipe = BSRecipe(name, epoch, version, revision) | 265 | bsrecipe = BSRecipe(name, epoch, version, revision) |
245 | for task in os.listdir(recipe_dir): | 266 | for task in os.listdir(recipe_dir): |
246 | bsrecipe.tasks[task] = BSTask.from_file( | 267 | bsrecipe.tasks[task] = BSTask.from_file( |
247 | os.path.join(recipe_dir, task)) | 268 | os.path.join(recipe_dir, task), build_end) |
248 | if name in buildstats: | 269 | if name in buildstats: |
249 | raise BSError("Cannot handle multiple versions of the same " | 270 | raise BSError("Cannot handle multiple versions of the same " |
250 | "package ({})".format(name)) | 271 | "package ({})".format(name)) |