bitbake: main: Add an option to specify what to profile

Starting with python 3.12, profiling now stays enabled over threads yet
you can't extract the profile data in the threads themselves, which makes it
difficult to use for our use case.

Our main loop starts the idle loop which starts the parsing threads and this
means we can't profile in the main loop and the parsing threads or the idle
loop at the same time due to this.

Add options to the commandline so you can specify which piece of bitbake
you want to enable profiling for. This allows some profiling with python 3.12
onwards rather than crashing.

(Bitbake rev: 09f29a4968841ee5070f70277ba8c253bb14f017)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Richard Purdie 2025-07-16 16:15:31 +01:00
parent b7173ca225
commit f209f127e6
4 changed files with 9 additions and 7 deletions

View File

@ -30,7 +30,7 @@ logfile = sys.argv[4]
lockname = sys.argv[5]
sockname = sys.argv[6]
timeout = float(sys.argv[7])
profile = bool(int(sys.argv[8]))
profile = sys.argv[8]
xmlrpcinterface = (sys.argv[9], int(sys.argv[10]))
if xmlrpcinterface[0] == "None":
xmlrpcinterface = (None, xmlrpcinterface[1])

View File

@ -2027,7 +2027,7 @@ class Parser(multiprocessing.Process):
self.exit = True
def run(self):
bb.utils.profile_function(self.profile, self.realrun, "profile-parse-%s.log" % multiprocessing.current_process().name, process=False)
bb.utils.profile_function("parsing" in self.profile, self.realrun, "profile-parse-%s.log" % multiprocessing.current_process().name, process=False)
def realrun(self):
# Signal handling here is hard. We must not terminate any process or thread holding the write

View File

@ -208,8 +208,10 @@ def create_bitbake_parser():
"failed and anything depending on it cannot be built, as much as "
"possible will be built before stopping.")
exec_group.add_argument("-P", "--profile", action="store_true",
help="Profile the command and save reports.")
exec_group.add_argument("-P", "--profile", action="append",
default=[],
help="Profile the command and save reports. Specify 'main', 'idle' or 'parsing' "
"to indicate which bitbake code to profile.")
exec_group.add_argument("-S", "--dump-signatures", action="append",
default=[], metavar="SIGNATURE_HANDLER",

View File

@ -137,7 +137,7 @@ class ProcessServer():
serverlog("Error writing to lock file: %s" % str(e))
pass
return bb.utils.profile_function(self.cooker.configuration.profile, self.main, "profile-mainloop.log")
return bb.utils.profile_function("main" in self.cooker.configuration.profile, self.main, "profile-mainloop.log")
def _idle_check(self):
return len(self._idlefuns) == 0 and self.cooker.command.currentAsyncCommand is None
@ -398,7 +398,7 @@ class ProcessServer():
serverlog("".join(msg))
def idle_thread(self):
bb.utils.profile_function(self.cooker.configuration.profile, self.idle_thread_internal, "profile-idleloop.log")
bb.utils.profile_function("idle" in self.cooker.configuration.profile, self.idle_thread_internal, "profile-idleloop.log")
def idle_thread_internal(self):
def remove_idle_func(function):
@ -600,7 +600,7 @@ class BitBakeServer(object):
os.set_inheritable(self.bitbake_lock.fileno(), True)
os.set_inheritable(self.readypipein, True)
serverscript = os.path.realpath(os.path.dirname(__file__) + "/../../../bin/bitbake-server")
os.execl(sys.executable, sys.executable, serverscript, "decafbad", str(self.bitbake_lock.fileno()), str(self.readypipein), self.logfile, self.bitbake_lock.name, self.sockname, str(self.server_timeout or 0), str(int(self.profile)), str(self.xmlrpcinterface[0]), str(self.xmlrpcinterface[1]))
os.execl(sys.executable, sys.executable, serverscript, "decafbad", str(self.bitbake_lock.fileno()), str(self.readypipein), self.logfile, self.bitbake_lock.name, self.sockname, str(self.server_timeout or 0), str(list(self.profile)), str(self.xmlrpcinterface[0]), str(self.xmlrpcinterface[1]))
def execServer(lockfd, readypipeinfd, lockname, sockname, server_timeout, xmlrpcinterface, profile):