Skip to content

Commit 8b96ca5

Browse files
Flowdalicthesamesam
authored andcommitted
process: do not poll join() in MultiprocessingProcesss
Based on the initial analysis of Esteve Varela Colominas, the polling on join() with the fixed 100ms delay incurs a significant performance penalty, especially for short-lived processes. And since portage is prone to spawning many of those, the penalty adds up easily. Instead of pooling proc.join() with a fixed 100ms delay, we now use the blocking variant of join() started in an executor which we await in the coroutine. Before this change: ( cd lib; python3 -m timeit 'import portage.process; portage.process.spawn("true")' ) 2 loops, best of 5: 104 msec per loop After this change: ( cd lib; python3 -m timeit 'import portage.process; portage.process.spawn("true")' ) 50 loops, best of 5: 4.45 msec per loop Bug: https://bugs.gentoo.org/958635 Signed-off-by: Florian Schmaus <[email protected]> Part-of: #1452 Closes: #1452 Signed-off-by: Sam James <[email protected]>
1 parent 4d2501d commit 8b96ca5

File tree

1 file changed

+1
-11
lines changed

1 file changed

+1
-11
lines changed

lib/portage/process.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,6 @@ class MultiprocessingProcess(AbstractProcess):
426426
An object that wraps OS processes created by multiprocessing.Process.
427427
"""
428428

429-
# Number of seconds between poll attempts for process exit status
430-
# (after the sentinel has become ready).
431-
_proc_join_interval = 0.1
432-
433429
def __init__(self, proc: multiprocessing.Process):
434430
self._proc = proc
435431
self.pid = proc.pid
@@ -480,13 +476,7 @@ async def _proc_join(self):
480476
except ValueError:
481477
pass
482478

483-
# Now that proc.sentinel is ready, poll until process exit
484-
# status has become available.
485-
while True:
486-
proc.join(0)
487-
if proc.exitcode is not None:
488-
break
489-
await asyncio.sleep(self._proc_join_interval, loop=loop)
479+
await loop.run_in_executor(None, proc.join)
490480

491481
def _proc_join_done(self, future):
492482
# The join task should never be cancelled, so let it raise

0 commit comments

Comments
 (0)