From 4897f7028f7947f32fdb1fd168f50c1ce41f171f Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Mon, 28 Sep 2026 20:33:33 +0200 Subject: [PATCH] legacy remote: use deques for the RPC call queues, fixes #10450 LegacyRemoteRepository.call_many took the next call from the front of a list (calls.pop(0)), which moves all the remaining entries each time. get_many() passes all ids at once, so borg transfer --from-borg1 --chunker-params (which fetches all chunks of an item via fetch_many) from a remote borg 1.x repository was quadratic in the chunk count of the item. Use collections.deque with popleft() for calls and waiting_for. Co-Authored-By: Claude Opus 5.5 --- src/borg/legacy/remote.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/borg/legacy/remote.py b/src/borg/legacy/remote.py index 2109000abd..df373aedd7 100644 --- a/src/borg/legacy/remote.py +++ b/src/borg/legacy/remote.py @@ -10,6 +10,7 @@ import textwrap import time import traceback +from collections import deque from subprocess import Popen, PIPE import borg.logger @@ -462,8 +463,8 @@ def handle_error(unpacked): else: raise self.RPCError(unpacked) - calls = list(calls) - waiting_for = [] + calls = deque(calls) + waiting_for = deque() send_buffer() # Try to send data, as some cases (async_response) will never try to send data otherwise. try: while wait or calls: @@ -479,7 +480,7 @@ def handle_error(unpacked): while waiting_for: try: unpacked = self.responses.pop(waiting_for[0]) - waiting_for.pop(0) + waiting_for.popleft() handle_error(unpacked) result = unpacked[RESULT] if self.borg1_server and cmd in BYTES_RESULT_METHODS: @@ -565,7 +566,7 @@ def handle_error(unpacked): _logger.warning("stderr: " + line.decode().strip()) if w: while not self.to_send and calls and len(waiting_for) < MAX_INFLIGHT: - args = calls.pop(0) + args = calls.popleft() self.msgid += 1 waiting_for.append(self.msgid) self.to_send.push_back(msgpack.packb({MSGID: self.msgid, MSG: cmd, ARGS: args}))