diff options
author | Joshua Watt <JPEWhacker@gmail.com> | 2025-07-08 09:42:22 -0600 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2025-07-09 06:40:58 +0100 |
commit | 5adeefd63fd499fee13c77fb4c1da8ef2f128377 (patch) | |
tree | d295c3a05717233df9940b0c4d53dff8e4c7e4f1 | |
parent | 51d825b367971e8b63e704de4ff4419ba7afaa05 (diff) | |
download | poky-5adeefd63fd499fee13c77fb4c1da8ef2f128377.tar.gz |
bitbake: cooker: Use shared counter for processing parser jobs
Instead of pre-partitioning which jobs will go to which parser
processes, pass the list of all jobs to all the parser processes
(efficiently via fork()), then used a shared counter of the next index
in the list that needs to be processed. This allows the parser processes
to run independently of needing to be feed by the parent process, and
load balances them much better.
(Bitbake rev: 373c4ddaf0e8128cc4f7d47aefa9860bd477a00f)
Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | bitbake/lib/bb/cooker.py | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py index 2bb80e330d..dc131939ed 100644 --- a/bitbake/lib/bb/cooker.py +++ b/bitbake/lib/bb/cooker.py | |||
@@ -26,6 +26,7 @@ import json | |||
26 | import pickle | 26 | import pickle |
27 | import codecs | 27 | import codecs |
28 | import hashserv | 28 | import hashserv |
29 | import ctypes | ||
29 | 30 | ||
30 | logger = logging.getLogger("BitBake") | 31 | logger = logging.getLogger("BitBake") |
31 | collectlog = logging.getLogger("BitBake.Collection") | 32 | collectlog = logging.getLogger("BitBake.Collection") |
@@ -1998,8 +1999,9 @@ class ParsingFailure(Exception): | |||
1998 | Exception.__init__(self, realexception, recipe) | 1999 | Exception.__init__(self, realexception, recipe) |
1999 | 2000 | ||
2000 | class Parser(multiprocessing.Process): | 2001 | class Parser(multiprocessing.Process): |
2001 | def __init__(self, jobs, results, quit, profile): | 2002 | def __init__(self, jobs, next_job_id, results, quit, profile): |
2002 | self.jobs = jobs | 2003 | self.jobs = jobs |
2004 | self.next_job_id = next_job_id | ||
2003 | self.results = results | 2005 | self.results = results |
2004 | self.quit = quit | 2006 | self.quit = quit |
2005 | multiprocessing.Process.__init__(self) | 2007 | multiprocessing.Process.__init__(self) |
@@ -2065,10 +2067,14 @@ class Parser(multiprocessing.Process): | |||
2065 | break | 2067 | break |
2066 | 2068 | ||
2067 | job = None | 2069 | job = None |
2068 | try: | 2070 | if havejobs: |
2069 | job = self.jobs.pop() | 2071 | with self.next_job_id.get_lock(): |
2070 | except IndexError: | 2072 | if self.next_job_id.value < len(self.jobs): |
2071 | havejobs = False | 2073 | job = self.jobs[self.next_job_id.value] |
2074 | self.next_job_id.value += 1 | ||
2075 | else: | ||
2076 | havejobs = False | ||
2077 | |||
2072 | if job: | 2078 | if job: |
2073 | result = self.parse(*job) | 2079 | result = self.parse(*job) |
2074 | # Clear the siggen cache after parsing to control memory usage, its huge | 2080 | # Clear the siggen cache after parsing to control memory usage, its huge |
@@ -2134,13 +2140,13 @@ class CookerParser(object): | |||
2134 | 2140 | ||
2135 | self.bb_caches = bb.cache.MulticonfigCache(self.cfgbuilder, self.cfghash, cooker.caches_array) | 2141 | self.bb_caches = bb.cache.MulticonfigCache(self.cfgbuilder, self.cfghash, cooker.caches_array) |
2136 | self.fromcache = set() | 2142 | self.fromcache = set() |
2137 | self.willparse = set() | 2143 | self.willparse = [] |
2138 | for mc in self.cooker.multiconfigs: | 2144 | for mc in self.cooker.multiconfigs: |
2139 | for filename in self.mcfilelist[mc]: | 2145 | for filename in self.mcfilelist[mc]: |
2140 | appends = self.cooker.collections[mc].get_file_appends(filename) | 2146 | appends = self.cooker.collections[mc].get_file_appends(filename) |
2141 | layername = self.cooker.collections[mc].calc_bbfile_priority(filename)[2] | 2147 | layername = self.cooker.collections[mc].calc_bbfile_priority(filename)[2] |
2142 | if not self.bb_caches[mc].cacheValid(filename, appends): | 2148 | if not self.bb_caches[mc].cacheValid(filename, appends): |
2143 | self.willparse.add((mc, self.bb_caches[mc], filename, appends, layername)) | 2149 | self.willparse.append((mc, self.bb_caches[mc], filename, appends, layername)) |
2144 | else: | 2150 | else: |
2145 | self.fromcache.add((mc, self.bb_caches[mc], filename, appends, layername)) | 2151 | self.fromcache.add((mc, self.bb_caches[mc], filename, appends, layername)) |
2146 | 2152 | ||
@@ -2159,18 +2165,18 @@ class CookerParser(object): | |||
2159 | def start(self): | 2165 | def start(self): |
2160 | self.results = self.load_cached() | 2166 | self.results = self.load_cached() |
2161 | self.processes = [] | 2167 | self.processes = [] |
2168 | |||
2162 | if self.toparse: | 2169 | if self.toparse: |
2163 | bb.event.fire(bb.event.ParseStarted(self.toparse), self.cfgdata) | 2170 | bb.event.fire(bb.event.ParseStarted(self.toparse), self.cfgdata) |
2164 | 2171 | ||
2172 | next_job_id = multiprocessing.Value(ctypes.c_int, 0) | ||
2165 | self.parser_quit = multiprocessing.Event() | 2173 | self.parser_quit = multiprocessing.Event() |
2166 | self.result_queue = multiprocessing.Queue() | 2174 | self.result_queue = multiprocessing.Queue() |
2167 | 2175 | ||
2168 | def chunkify(lst,n): | 2176 | # Have to pass in willparse at fork time so all parsing processes have the unpickleable data |
2169 | return [lst[i::n] for i in range(n)] | 2177 | # then access it by index from the parse queue. |
2170 | self.jobs = chunkify(list(self.willparse), self.num_processes) | ||
2171 | |||
2172 | for i in range(0, self.num_processes): | 2178 | for i in range(0, self.num_processes): |
2173 | parser = Parser(self.jobs[i], self.result_queue, self.parser_quit, self.cooker.configuration.profile) | 2179 | parser = Parser(self.willparse, next_job_id, self.result_queue, self.parser_quit, self.cooker.configuration.profile) |
2174 | parser.start() | 2180 | parser.start() |
2175 | self.process_names.append(parser.name) | 2181 | self.process_names.append(parser.name) |
2176 | self.processes.append(parser) | 2182 | self.processes.append(parser) |