summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorRoss Burton <ross.burton@arm.com>2023-02-14 16:46:14 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-02-17 18:01:01 +0000
commit163aa6f1490b00d36c42611c77fc61b71ced601d (patch)
treeb821a0057d100ed44389dca55734b3168d77564d /scripts
parent6807f364470b63370524d1966a8973ad56f163ee (diff)
downloadpoky-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.py33
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))