Performance of `consume_socket_output` is n² where it could be just `n`
I noticed that the function is repeatedly concatenating bytes:
def consume_socket_output(frames, demux=False):
...
# If the streams are demultiplexed, the generator yields tuples
# (stdout, stderr)
out = [None, None]
for frame in frames:
# It is guaranteed that for each frame, one and only one stream
# is not None.
assert frame != (None, None)
if frame[0] is not None:
if out[0] is None:
out[0] = frame[0]
else:
out[0] += frame[0]
else:
if out[1] is None:
out[1] = frame[1]
else:
out[1] += frame[1]
return tuple(out)
This makes it extremely slow for long inputs. I noticed since I used dockerpy to get about 1GB of process output, which took hours and blocked 100% CPU for the entire time.
The fix for it should be pretty simple, just collect all the frames and use b''.join(frames) instead:
# If the streams are demultiplexed, the generator yields tuples
# (stdout, stderr)
stdout = []
stderr = []
for stdout_frame, stderr_frame in frames:
# It is guaranteed that for each frame, one and only one stream
# is not None.
if stdout_frame:
stdout.append(stdout_frame)
else:
stderr.append(stderr_frame)
stdout = b''.join(stdout) if len(stdout) > 0 else None
stderr = b''.join(stderr) if len(stderr) > 0 else None
return stdout, stderr
Thanks for raising the issue. @GeorchW, would you like to provide the proposed PR?
Sure, can you give me some directions as to what's needed on top? Do I have to add a test or something?
@kiview sorry if it comes as rude but it feels really bad to be asked for a PR and then getting no reaction after creating it...
this project feels pretty much unmaintained at this point