Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 84e4316

Browse files
committed
Issue #17025: multiprocessing: Reduce Queue and SimpleQueue contention.
1 parent bb25b6f commit 84e4316

2 files changed

Lines changed: 28 additions & 43 deletions

File tree

Lib/multiprocessing/queues.py

Lines changed: 26 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from multiprocessing.connection import Pipe
2323
from multiprocessing.synchronize import Lock, BoundedSemaphore, Semaphore, Condition
2424
from multiprocessing.util import debug, info, Finalize, register_after_fork
25-
from multiprocessing.forking import assert_spawning
25+
from multiprocessing.forking import assert_spawning, ForkingPickler
2626

2727
#
2828
# Queue type using a pipe, buffer and thread
@@ -69,8 +69,8 @@ def _after_fork(self):
6969
self._joincancelled = False
7070
self._closed = False
7171
self._close = None
72-
self._send = self._writer.send
73-
self._recv = self._reader.recv
72+
self._send_bytes = self._writer.send_bytes
73+
self._recv_bytes = self._reader.recv_bytes
7474
self._poll = self._reader.poll
7575

7676
def put(self, obj, block=True, timeout=None):
@@ -89,14 +89,9 @@ def put(self, obj, block=True, timeout=None):
8989

9090
def get(self, block=True, timeout=None):
9191
if block and timeout is None:
92-
self._rlock.acquire()
93-
try:
94-
res = self._recv()
95-
self._sem.release()
96-
return res
97-
finally:
98-
self._rlock.release()
99-
92+
with self._rlock:
93+
res = self._recv_bytes()
94+
self._sem.release()
10095
else:
10196
if block:
10297
deadline = time.time() + timeout
@@ -109,11 +104,12 @@ def get(self, block=True, timeout=None):
109104
raise Empty
110105
elif not self._poll():
111106
raise Empty
112-
res = self._recv()
107+
res = self._recv_bytes()
113108
self._sem.release()
114-
return res
115109
finally:
116110
self._rlock.release()
111+
# unserialize the data after having released the lock
112+
return ForkingPickler.loads(res)
117113

118114
def qsize(self):
119115
# Raises NotImplementedError on Mac OSX because of broken sem_getvalue()
@@ -158,7 +154,7 @@ def _start_thread(self):
158154
self._buffer.clear()
159155
self._thread = threading.Thread(
160156
target=Queue._feed,
161-
args=(self._buffer, self._notempty, self._send,
157+
args=(self._buffer, self._notempty, self._send_bytes,
162158
self._wlock, self._writer.close, self._ignore_epipe),
163159
name='QueueFeederThread'
164160
)
@@ -210,7 +206,7 @@ def _finalize_close(buffer, notempty):
210206
notempty.release()
211207

212208
@staticmethod
213-
def _feed(buffer, notempty, send, writelock, close, ignore_epipe):
209+
def _feed(buffer, notempty, send_bytes, writelock, close, ignore_epipe):
214210
debug('starting thread to feed data to pipe')
215211
from .util import is_exiting
216212

@@ -241,16 +237,14 @@ def _feed(buffer, notempty, send, writelock, close, ignore_epipe):
241237
close()
242238
return
243239

240+
# serialize the data before acquiring the lock
241+
obj = ForkingPickler.dumps(obj)
244242
if wacquire is None:
245-
send(obj)
246-
# Delete references to object. See issue16284
247-
del obj
243+
send_bytes(obj)
248244
else:
249245
wacquire()
250246
try:
251-
send(obj)
252-
# Delete references to object. See issue16284
253-
del obj
247+
send_bytes(obj)
254248
finally:
255249
wrelease()
256250
except IndexError:
@@ -344,7 +338,6 @@ def __init__(self):
344338
self._wlock = None
345339
else:
346340
self._wlock = Lock()
347-
self._make_methods()
348341

349342
def empty(self):
350343
return not self._poll()
@@ -355,29 +348,19 @@ def __getstate__(self):
355348

356349
def __setstate__(self, state):
357350
(self._reader, self._writer, self._rlock, self._wlock) = state
358-
self._make_methods()
359351

360-
def _make_methods(self):
361-
recv = self._reader.recv
362-
racquire, rrelease = self._rlock.acquire, self._rlock.release
363-
def get():
364-
racquire()
365-
try:
366-
return recv()
367-
finally:
368-
rrelease()
369-
self.get = get
352+
def get(self):
353+
with self._rlock:
354+
res = self._reader.recv_bytes()
355+
# unserialize the data after having released the lock
356+
return ForkingPickler.loads(res)
370357

358+
def put(self, obj):
359+
# serialize the data before acquiring the lock
360+
obj = ForkingPickler.dumps(obj)
371361
if self._wlock is None:
372362
# writes to a message oriented win32 pipe are atomic
373-
self.put = self._writer.send
363+
self._writer.send_bytes(obj)
374364
else:
375-
send = self._writer.send
376-
wacquire, wrelease = self._wlock.acquire, self._wlock.release
377-
def put(obj):
378-
wacquire()
379-
try:
380-
return send(obj)
381-
finally:
382-
wrelease()
383-
self.put = put
365+
with self._wlock:
366+
self._writer.send_bytes(obj)

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ Core and Builtins
294294
Library
295295
-------
296296

297+
- Issue #17025: multiprocessing: Reduce Queue and SimpleQueue contention.
298+
297299
- Issue #17536: Add to webbrowser's browser list: www-browser, x-www-browser,
298300
iceweasel, iceape.
299301

0 commit comments

Comments
 (0)