diff options
author | Etienne Cordonnier <ecordonnier@snap.com> | 2023-09-21 09:56:58 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-11-06 16:45:11 +0000 |
commit | f1b0ab7e4b1cfeabaa8f981175e503d0c435ba0b (patch) | |
tree | 224e12e16188e74ca46679952ef608d4d593c419 /bitbake/bin | |
parent | 7de36b25d1df97b105fb52b5dc3c62ab1800fb3a (diff) | |
download | poky-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-x | bitbake/bin/bitbake-worker | 34 |
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) |