classification
Title: release GIL on mmap dealloc
Type: performance Stage: resolved
Components: Library (Lib) Versions: Python 3.8, Python 3.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: benjamin.peterson, christian.heimes, davide.rizzo, davin, ezio.melotti, inada.naoki, vstinner
Priority: normal Keywords: patch

Created on 2019-02-27 18:00 by davide.rizzo, last changed 2019-03-07 11:41 by vstinner. This issue is now closed.

Files
File name Uploaded Description Edit
unmap.c davide.rizzo, 2019-02-28 11:35
Pull Requests
URL Status Linked Edit
PR 12073 merged python-dev, 2019-02-27 18:07
PR 12198 closed vstinner, 2019-03-06 16:36
PR 12199 merged davide.rizzo, 2019-03-06 16:42
Messages (18)
msg336775 - (view) Author: Davide Rizzo (davide.rizzo) * Date: 2019-02-27 18:00
munmap() can take a long time. I think mmap_object_dealloc can trivially release the GIL around this operation. Something similar was already mentioned in https://bugs.python.org/issue1572968 but a general patch was never provided. The dealloc case alone is significant enough to deserve fixing.
msg336813 - (view) Author: Inada Naoki (inada.naoki) * (Python committer) Date: 2019-02-28 08:12
Your patch is modifying obmalloc.
It uses MAP_PRIVATE|MAP_ANONYMOUS mmap.
Does it really take log time?  How?

#1572968 is different.  It is mmap module.  It can use file-backed mmap.  It is I/O.
msg336817 - (view) Author: Inada Naoki (inada.naoki) * (Python committer) Date: 2019-02-28 08:38
Sorry, I messed up.  Your PR is changing mmap module, not obmalloc.
msg336819 - (view) Author: Davide Rizzo (davide.rizzo) * Date: 2019-02-28 09:15
Yes, this is mmap module. I found this to be slow for posix-shm-backed mmaps. Several milliseconds, like 20ms for a 128 MB object. Maybe the same can happen with private|anon mmaps? I will follow up with more numbers.
msg336827 - (view) Author: Davide Rizzo (davide.rizzo) * Date: 2019-02-28 11:35
munmap() of private maps is usually pretty fast but not negligible (2 ms for 1GB). Shared maps are much slower. For some reason, shared maps explicitly backed by POSIX shared memory stand in between but are still pretty slow.

If someone cares about file-backed mmaps I can test those too. I thought this is already significant to justify releasing the GIL.


This is on Linux 4.4:


shared anon mmap 1048576 bytes
mmap time             6,393 ns
write time          449,062 ns
munmap time         100,205 ns
--
private anon mmap 1048576 bytes
mmap time             2,168 ns
write time          308,966 ns
munmap time          36,930 ns
--
posix shm + mmap 1048576 bytes
mmap time            13,299 ns
write time          369,305 ns
close time            1,545 ns
munmap time          26,759 ns
--

shared anon mmap 134217728 bytes
mmap time             4,641 ns
write time       64,508,536 ns
munmap time      13,592,556 ns
--
private anon mmap 134217728 bytes
mmap time             6,116 ns
write time       25,402,084 ns
munmap time         388,976 ns
--
posix shm + mmap 134217728 bytes
mmap time            29,034 ns
write time       66,826,645 ns
close time            3,707 ns
munmap time       3,475,977 ns
--

shared anon mmap 1073741824 bytes
mmap time            11,127 ns
write time      508,227,373 ns
munmap time      94,885,306 ns
--
private anon mmap 1073741824 bytes
mmap time             7,133 ns
write time      199,933,903 ns
munmap time       2,361,036 ns
--
posix shm + mmap 1073741824 bytes
mmap time            24,868 ns
write time      527,566,819 ns
close time            4,015 ns
munmap time      21,179,674 ns
--
msg336829 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2019-02-28 12:00
The change sounds like a good idea and should be backported, too.

IIRC mmap() performance also depends on MMU and TLB speed. In the past I have seen paravirtualized systems with poor MMU performance that caused fork() to be slow and Redis to hang.
msg337317 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2019-03-06 15:52
New changeset bb9593af0ac835b93c2834d44b72fa34e30efed0 by Benjamin Peterson (Davide Rizzo) in branch 'master':
closes bpo-36139: release GIL around munmap(). (GH-12073)
https://github.com/python/cpython/commit/bb9593af0ac835b93c2834d44b72fa34e30efed0
msg337320 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-06 16:31
This change broke the Windows 7 buildbot:
https://buildbot.python.org/all/#/builders/40/builds/1745

Example:

0:01:34 [ 66/420/1] test_mmap crashed (Exit code 2147483651) -- running: test_tools (1 min 22 sec)
Fatal Python error: Python memory allocator called without holding the GIL

Current thread 0x00000de4 (most recent call first):
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\test_mmap.py", line 645 in test_crasher_on_windows
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\case.py", line 642 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\case.py", line 702 in __call__
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 122 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 84 in __call__
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 122 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 84 in __call__
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 122 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 84 in __call__
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\runner.py", line 176 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\support\__init__.py", line 1968 in _run_suite
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\support\__init__.py", line 2064 in run_unittest
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\runtest.py", line 178 in test_runner
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\runtest.py", line 182 in runtest_inner
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\runtest.py", line 127 in runtest
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\runtest_mp.py", line 68 in run_tests_worker
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\main.py", line 600 in _main
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\main.py", line 586 in main
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\main.py", line 640 in main
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\regrtest.py", line 46 in _main
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\regrtest.py", line 50 in <module>
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\runpy.py", line 85 in _run_code
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\runpy.py", line 192 in _run_module_as_main
Windows fatal exception: code 0x80000003

Current thread 0x00000de4 (most recent call first):
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\test_mmap.py", line 645 in test_crasher_on_windows
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\case.py", line 642 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\case.py", line 702 in __call__
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 122 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 84 in __call__
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 122 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 84 in __call__
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 122 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\suite.py", line 84 in __call__
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\unittest\runner.py", line 176 in run
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\support\__init__.py", line 1968 in _run_suite
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\support\__init__.py", line 2064 in run_unittest
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\runtest.py", line 178 in test_runner
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\runtest.py", line 182 in runtest_inner
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\runtest.py", line 127 in runtest
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\runtest_mp.py", line 68 in run_tests_worker
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\main.py", line 600 in _main
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\main.py", line 586 in main
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\libregrtest\main.py", line 640 in main
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\regrtest.py", line 46 in _main
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\regrtest.py", line 50 in <module>
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\runpy.py", line 85 in _run_code
  File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\runpy.py", line 192 in _run_module_as_main
msg337322 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-06 16:34
The bug:
https://github.com/python/cpython/pull/12073/files#r263026496
msg337323 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-06 16:38
The bug:
https://github.com/python/cpython/pull/12073/files#r263026496
(correct link, sorry)

--

If nobody comes up quickly with a fix, I will revert the change to repair Windows buildbots: PR 12198, as part of the buildbot policy ("revert on failure"). I don't have the bandwidth to dig into this failure.
https://pythondev.readthedocs.io/ci.html#revert-on-fail
msg337324 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-06 16:40
"""
r263026496">https://github.com/python/cpython/pull/12073/files#r263026496
"""

Oh wow, that's really strange. I'm sure that I wrote "https://..." URL but my URL became "r263026496">https://..." !?

3rd attempt to post the link:
https://github.com/python/cpython/pull/12073/files#r263026496

Anyway, my link points to my comment:

"""


PyMem_Free(m_obj->tagname) is called below without holding the GIL: that's illegal. Other move the call to free when the GIL is hold again, or use PyMem_RawFree().

"Warning: The GIL must be held when using these functions. "
https://docs.python.org/dev/c-api/memory.html#memory-interface

Note: You can use PYTHONMALLOC=debug or -X dev to reproduce the issue on a Python compiled in release mode.
"""

On the #ifdef MS_WINDOWS path of mmap_object_dealloc().
msg337325 - (view) Author: Davide Rizzo (davide.rizzo) * Date: 2019-03-06 16:42
Thanks Victor. I think this fixes it https://github.com/python/cpython/pull/12199
msg337326 - (view) Author: Davide Rizzo (davide.rizzo) * Date: 2019-03-06 16:50
BTW should this be backported to 3.7?
msg337333 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-06 17:08
New changeset dc078947a5033a048d804e244e847b5844734439 by Victor Stinner (Davide Rizzo) in branch 'master':
bpo-36139: Fix mmap_object_dealloc(): hold the GIL to call PyMem_Free() (GH-12199)
https://github.com/python/cpython/commit/dc078947a5033a048d804e244e847b5844734439
msg337334 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-06 17:09
The second commit does fix the regression (I tested manually on Windows with Python compiled in debug mode).
msg337355 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2019-03-07 03:35
> Oh wow, that's really strange. I'm sure that I wrote "https://..." URL but my URL became "r263026496">https://..." !?

The links are now fixed (Roundup was getting confused by the rNNNNNN, since it looks like a SVN revision).
msg337386 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-07 11:41
4th attempt (sorry for the spam, it's just to check the Roundup fix!):
https://github.com/python/cpython/pull/12073/files#r263026496
msg337387 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-03-07 11:41
Yeah! Roundup is fixed, thanks Ezio!
History
Date User Action Args
2019-03-07 11:41:30vstinnersetmessages: + msg337387
2019-03-07 11:41:15vstinnersetmessages: + msg337386
2019-03-07 03:35:23ezio.melottisettype: performance

messages: + msg337355
nosy: + ezio.melotti
2019-03-06 17:09:28vstinnersetstatus: open -> closed
resolution: fixed
messages: + msg337334

stage: patch review -> resolved
2019-03-06 17:08:33vstinnersetmessages: + msg337333
2019-03-06 16:50:39davide.rizzosetmessages: + msg337326
2019-03-06 16:42:56davide.rizzosetmessages: + msg337325
2019-03-06 16:42:12davide.rizzosetpull_requests: + pull_request12194
2019-03-06 16:40:34vstinnersetmessages: + msg337324
2019-03-06 16:38:29vstinnersetmessages: + msg337323
2019-03-06 16:36:41vstinnersetstage: resolved -> patch review
pull_requests: + pull_request12193
2019-03-06 16:34:10vstinnersetmessages: + msg337322
2019-03-06 16:31:57vstinnersetstatus: closed -> open

nosy: + vstinner
messages: + msg337320

resolution: fixed -> (no value)
2019-03-06 15:52:44benjamin.petersonsetstatus: open -> closed

nosy: + benjamin.peterson
messages: + msg337317

resolution: fixed
stage: patch review -> resolved
2019-02-28 12:00:05christian.heimessetnosy: + christian.heimes, davin

messages: + msg336829
versions: + Python 3.7
2019-02-28 11:35:25davide.rizzosetfiles: + unmap.c

messages: + msg336827
2019-02-28 09:15:51davide.rizzosetmessages: + msg336819
2019-02-28 08:38:23inada.naokisetmessages: + msg336817
2019-02-28 08:12:00inada.naokisetnosy: + inada.naoki
messages: + msg336813
2019-02-27 18:07:17python-devsetkeywords: + patch
stage: patch review
pull_requests: + pull_request12092
2019-02-27 18:00:41davide.rizzocreate