summaryrefslogtreecommitdiffstats
path: root/bitbake/bin
diff options
context:
space:
mode:
authorEtienne Cordonnier <ecordonnier@snap.com>2023-09-21 09:56:58 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-11-06 16:45:11 +0000
commitf1b0ab7e4b1cfeabaa8f981175e503d0c435ba0b (patch)
tree224e12e16188e74ca46679952ef608d4d593c419 /bitbake/bin
parent7de36b25d1df97b105fb52b5dc3c62ab1800fb3a (diff)
downloadpoky-f1b0ab7e4b1cfeabaa8f981175e503d0c435ba0b.tar.gz
bitbake: bitbake-worker: add header with length of message
The IPC mechanism between runqueue.py and bitbake-worker is currently not scalable: The data is sent with the format <tag>pickled-data</tag>, and bitbake-worker has no information about the size of the message. Therefore, the bitbake-worker is calling select() and read() in a loop, and then calling "self.queue.find(b"</" + item + b">")" for each chunk received. This does not scale, because queue.find has a linear complexity relative to the size of the queue, and workerdata messages get very big e.g. for builds which reference a lot of files in SRC_URI. The number of chunks varies, but on my test system a lot of chunks of 65536 bytes are sent, and each iteration takes 0.1 seconds, making the transfer of the "workerdata" data very slow (on my test setup 35 seconds before this fix, and 1.5 seconds after this fix). This commit adds a 4 bytes header after <tag>, so that bitbake-worker knows how many bytes need to be received, and does not need to constantly search the whole queue for </tag>. (Bitbake rev: 595176d6be95a9c4718d3a40499d1eb576b535f5) Signed-off-by: Etienne Cordonnier <ecordonnier@snap.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/bin')
-rwxr-xr-xbitbake/bin/bitbake-worker34
1 files changed, 23 insertions, 11 deletions
diff --git a/bitbake/bin/bitbake-worker b/bitbake/bin/bitbake-worker
index 609e276fe2..eba9c562c7 100755
--- a/bitbake/bin/bitbake-worker
+++ b/bitbake/bin/bitbake-worker
@@ -433,18 +433,30 @@ class BitbakeWorker(object):
433 while self.process_waitpid(): 433 while self.process_waitpid():
434 continue 434 continue
435 435
436
437 def handle_item(self, item, func): 436 def handle_item(self, item, func):
438 if self.queue.startswith(b"<" + item + b">"): 437 opening_tag = b"<" + item + b">"
439 index = self.queue.find(b"</" + item + b">") 438 if not self.queue.startswith(opening_tag):
440 while index != -1: 439 return
441 try: 440
442 func(self.queue[(len(item) + 2):index]) 441 tag_len = len(opening_tag)
443 except pickle.UnpicklingError: 442 if len(self.queue) < tag_len + 4:
444 workerlog_write("Unable to unpickle data: %s\n" % ":".join("{:02x}".format(c) for c in self.queue)) 443 # we need to receive more data
445 raise 444 return
446 self.queue = self.queue[(index + len(item) + 3):] 445 header = self.queue[tag_len:tag_len + 4]
447 index = self.queue.find(b"</" + item + b">") 446 payload_len = int.from_bytes(header, 'big')
447 # closing tag has length (tag_len + 1)
448 if len(self.queue) < tag_len * 2 + 1 + payload_len:
449 # we need to receive more data
450 return
451
452 index = self.queue.find(b"</" + item + b">")
453 if index != -1:
454 try:
455 func(self.queue[(tag_len + 4):index])
456 except pickle.UnpicklingError:
457 workerlog_write("Unable to unpickle data: %s\n" % ":".join("{:02x}".format(c) for c in self.queue))
458 raise
459 self.queue = self.queue[(index + len(b"</") + len(item) + len(b">")):]
448 460
449 def handle_cookercfg(self, data): 461 def handle_cookercfg(self, data):
450 self.cookercfg = pickle.loads(data) 462 self.cookercfg = pickle.loads(data)