diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2025-07-16 15:56:38 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2025-07-17 10:45:57 +0100 |
commit | e16dd314450cb2b85e4984c17fa60403b662ef8c (patch) | |
tree | 0e3276eae79d9f130183188df5fa64698e66b466 /bitbake/lib | |
parent | 6933d4b57ef9b2b6bbc8c97069a4f54e46eb3e4d (diff) | |
download | poky-e16dd314450cb2b85e4984c17fa60403b662ef8c.tar.gz |
bitbake: cooker/process/utils: Create profiling common function to remove code duplication
We have code duplication in the way we handle profiling of code sections.
Create a common function in utils which covers this.
The main loop and idle loop profile files were also reversed. Fix this and the naming,
removing a couple of unused variables containing the profile log names in the process too.
(Bitbake rev: b4f6bae97ac9607420fc49fd4c9e957d89c9a5f3)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib')
-rw-r--r-- | bitbake/lib/bb/cooker.py | 16 | ||||
-rw-r--r-- | bitbake/lib/bb/server/process.py | 36 | ||||
-rw-r--r-- | bitbake/lib/bb/utils.py | 28 |
3 files changed, 31 insertions, 49 deletions
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py index dc131939ed..c60fcd2719 100644 --- a/bitbake/lib/bb/cooker.py +++ b/bitbake/lib/bb/cooker.py | |||
@@ -2027,21 +2027,7 @@ class Parser(multiprocessing.Process): | |||
2027 | self.exit = True | 2027 | self.exit = True |
2028 | 2028 | ||
2029 | def run(self): | 2029 | def run(self): |
2030 | 2030 | bb.utils.profile_function(self.profile, self.realrun, "profile-parse-%s.log" % multiprocessing.current_process().name, process=False) | |
2031 | if not self.profile: | ||
2032 | self.realrun() | ||
2033 | return | ||
2034 | |||
2035 | try: | ||
2036 | import cProfile as profile | ||
2037 | except: | ||
2038 | import profile | ||
2039 | prof = profile.Profile() | ||
2040 | try: | ||
2041 | profile.Profile.runcall(prof, self.realrun) | ||
2042 | finally: | ||
2043 | logfile = "profile-parse-%s.log" % multiprocessing.current_process().name | ||
2044 | prof.dump_stats(logfile) | ||
2045 | 2031 | ||
2046 | def realrun(self): | 2032 | def realrun(self): |
2047 | # Signal handling here is hard. We must not terminate any process or thread holding the write | 2033 | # Signal handling here is hard. We must not terminate any process or thread holding the write |
diff --git a/bitbake/lib/bb/server/process.py b/bitbake/lib/bb/server/process.py index 4b35be62cd..2c5057bff1 100644 --- a/bitbake/lib/bb/server/process.py +++ b/bitbake/lib/bb/server/process.py | |||
@@ -80,9 +80,6 @@ class idleFinish(): | |||
80 | self.msg = msg | 80 | self.msg = msg |
81 | 81 | ||
82 | class ProcessServer(): | 82 | class ProcessServer(): |
83 | profile_filename = "profile.log" | ||
84 | profile_processed_filename = "profile.log.processed" | ||
85 | |||
86 | def __init__(self, lock, lockname, sock, sockname, server_timeout, xmlrpcinterface): | 83 | def __init__(self, lock, lockname, sock, sockname, server_timeout, xmlrpcinterface): |
87 | self.command_channel = False | 84 | self.command_channel = False |
88 | self.command_channel_reply = False | 85 | self.command_channel_reply = False |
@@ -140,23 +137,7 @@ class ProcessServer(): | |||
140 | serverlog("Error writing to lock file: %s" % str(e)) | 137 | serverlog("Error writing to lock file: %s" % str(e)) |
141 | pass | 138 | pass |
142 | 139 | ||
143 | if self.cooker.configuration.profile: | 140 | return bb.utils.profile_function(self.cooker.configuration.profile, self.main, "profile-mainloop.log") |
144 | try: | ||
145 | import cProfile as profile | ||
146 | except: | ||
147 | import profile | ||
148 | prof = profile.Profile() | ||
149 | |||
150 | ret = profile.Profile.runcall(prof, self.main) | ||
151 | |||
152 | prof.dump_stats("profile.log") | ||
153 | bb.utils.process_profilelog("profile.log") | ||
154 | serverlog("Raw profiling information saved to profile.log and processed statistics to profile.log.processed") | ||
155 | |||
156 | else: | ||
157 | ret = self.main() | ||
158 | |||
159 | return ret | ||
160 | 141 | ||
161 | def _idle_check(self): | 142 | def _idle_check(self): |
162 | return len(self._idlefuns) == 0 and self.cooker.command.currentAsyncCommand is None | 143 | return len(self._idlefuns) == 0 and self.cooker.command.currentAsyncCommand is None |
@@ -417,20 +398,7 @@ class ProcessServer(): | |||
417 | serverlog("".join(msg)) | 398 | serverlog("".join(msg)) |
418 | 399 | ||
419 | def idle_thread(self): | 400 | def idle_thread(self): |
420 | if self.cooker.configuration.profile: | 401 | bb.utils.profile_function(self.cooker.configuration.profile, self.idle_thread_internal, "profile-idleloop.log") |
421 | try: | ||
422 | import cProfile as profile | ||
423 | except: | ||
424 | import profile | ||
425 | prof = profile.Profile() | ||
426 | |||
427 | ret = profile.Profile.runcall(prof, self.idle_thread_internal) | ||
428 | |||
429 | prof.dump_stats("profile-mainloop.log") | ||
430 | bb.utils.process_profilelog("profile-mainloop.log") | ||
431 | serverlog("Raw profiling information saved to profile-mainloop.log and processed statistics to profile-mainloop.log.processed") | ||
432 | else: | ||
433 | self.idle_thread_internal() | ||
434 | 402 | ||
435 | def idle_thread_internal(self): | 403 | def idle_thread_internal(self): |
436 | def remove_idle_func(function): | 404 | def remove_idle_func(function): |
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py index 1cc74ed546..f688f7dd68 100644 --- a/bitbake/lib/bb/utils.py +++ b/bitbake/lib/bb/utils.py | |||
@@ -1418,6 +1418,34 @@ def cpu_count(): | |||
1418 | def nonblockingfd(fd): | 1418 | def nonblockingfd(fd): |
1419 | fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) | 1419 | fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) |
1420 | 1420 | ||
1421 | def profile_function(profile, function, output_fn, process=True): | ||
1422 | """Common function to profile a code block and optionally process the | ||
1423 | output using or processing function. | ||
1424 | |||
1425 | Arguments: | ||
1426 | |||
1427 | - ``profile``: a boolean saying whether to enable profiling or not | ||
1428 | - ``function``: the function call to profile/run | ||
1429 | - ``outputfn``: where to write the profiling data | ||
1430 | - ``process``: whether to process the profiling data and write a report | ||
1431 | |||
1432 | Returns the wrapped function return value | ||
1433 | """ | ||
1434 | if profile: | ||
1435 | try: | ||
1436 | import cProfile as profile | ||
1437 | except: | ||
1438 | import profile | ||
1439 | prof = profile.Profile() | ||
1440 | ret = profile.Profile.runcall(prof, function) | ||
1441 | prof.dump_stats(output_fn) | ||
1442 | if process: | ||
1443 | process_profilelog(output_fn) | ||
1444 | serverlog("Raw profiling information saved to %s and processed statistics to %s.processed" % (output_fn, output_fn)) | ||
1445 | return ret | ||
1446 | else: | ||
1447 | return function() | ||
1448 | |||
1421 | def process_profilelog(fn, pout = None): | 1449 | def process_profilelog(fn, pout = None): |
1422 | # Either call with a list of filenames and set pout or a filename and optionally pout. | 1450 | # Either call with a list of filenames and set pout or a filename and optionally pout. |
1423 | if not pout: | 1451 | if not pout: |