Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context manager to temporarily disable GC #75537

Open
rhettinger opened this issue Sep 5, 2017 · 62 comments
Open

Add context manager to temporarily disable GC #75537

rhettinger opened this issue Sep 5, 2017 · 62 comments
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@rhettinger
Copy link
Contributor

BPO 31356
Nosy @rhettinger, @gpshead, @ncoghlan, @pitrou, @ned-deily, @pmp-p, @ericsnowcurrently, @serhiy-storchaka, @1st1, @MojoVampire, @YoSTEALTH, @bharel, @lisroach, @pablogsal, @sweeneyde, @Jongy
PRs
  • bpo-31356: Add context manager to temporarily disable GC #4224
  • bpo-31356: Fixing PyErr_WarnEx might error out. #5456
  • bpo-31356: Fix multiple errors in gc.ensure_disabled() #5462
  • Revert "bpo-31356: Add context manager to temporarily disable GC #4224 #5495
  • [3.7] Revert "bpo-31356: Add context manager to temporarily disable GC GH-5495 #5496
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2017-09-05.23:47:23.956>
    labels = ['interpreter-core', '3.8', 'type-feature', 'library']
    title = 'Add context manager to temporarily disable GC'
    updated_at = <Date 2021-05-01.15:07:54.862>
    user = 'https://github.com/rhettinger'

    bugs.python.org fields:

    activity = <Date 2021-05-01.15:07:54.862>
    actor = 'Yonatan Goldschmidt'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Interpreter Core', 'Library (Lib)']
    creation = <Date 2017-09-05.23:47:23.956>
    creator = 'rhettinger'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 31356
    keywords = ['patch']
    message_count = 52.0
    messages = ['301407', '301633', '301636', '301644', '301645', '301710', '301720', '302903', '305402', '306053', '306054', '306071', '306072', '306076', '311167', '311300', '311305', '311312', '311331', '311337', '311340', '311342', '311343', '311344', '311347', '311348', '311350', '311351', '311352', '311356', '311357', '311360', '311362', '311363', '311366', '311372', '311396', '311397', '311402', '311444', '311491', '311494', '311495', '311508', '311512', '311513', '311514', '311566', '311635', '311646', '385213', '385214']
    nosy_count = 16.0
    nosy_names = ['rhettinger', 'gregory.p.smith', 'ncoghlan', 'pitrou', 'ned.deily', 'pmpp', 'eric.snow', 'serhiy.storchaka', 'yselivanov', 'josh.r', 'YoSTEALTH', 'bar.harel', 'lisroach', 'pablogsal', 'Dennis Sweeney', 'Yonatan Goldschmidt']
    pr_nums = ['4224', '5456', '5462', '5495', '5496']
    priority = 'normal'
    resolution = None
    stage = 'needs patch'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue31356'
    versions = ['Python 3.8']

    @rhettinger
    Copy link
    Contributor Author

    Used like this:

        with gc_disabled():
            run_some_timing()
    
        with gc_disabled():
            # do_something_that_has_real_time_guarantees
            # such as a pair trade, robotic braking, etc

    This would be implemented in C for atomicity and speed. It would be roughly equivalent to:

        @contextmanager
        def gc_disabled():
            if gc.isenabled():
                gc.disable()
                yield
                gc.enable()
            else:
                yield

    @rhettinger rhettinger added 3.7 (EOL) end of life interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement labels Sep 5, 2017
    @ncoghlan
    Copy link
    Contributor

    ncoghlan commented Sep 7, 2017

    +1 from me for the general idea. As far as where to put it goes, I think the gc module would be the most appropriate home.

    @ncoghlan ncoghlan added the stdlib Python modules in the Lib dir label Sep 7, 2017
    @ncoghlan ncoghlan removed their assignment Sep 7, 2017
    @serhiy-storchaka
    Copy link
    Member

    Note that threads can break this. Even without calling gc.enable() explicitly, "with gc_disabled()" in different thread can enable GC inside other "with gc_disabled()" block.

    @ncoghlan
    Copy link
    Contributor

    ncoghlan commented Sep 7, 2017

    Yes, this will be in the same category as the standard stream redirection context managers - multi-threaded applications either won't be able to use it, or else will need to manage access to it somehow.

    @gpshead
    Copy link
    Member

    gpshead commented Sep 7, 2017

    I believe Raymond is aware of the thread issue. We discussed it.

    If gc.disable() would return the previous state of the gc instead of None and an API to enable based on a passed in bool, both of which are written in C and executed with the GIL (or merely another lock protecting changing the gc state rather than the GIL) held and this Python would works with multiple threads all fighting to control the gc state:

    @contextmanager
    def gc_disabled():
      previous_enable_state = gc.disable()
      yield
      gc.set_enable(previous_enable_state)

    But we don't need to modify gc.disable's return value or add a set_enable() if gc_disabled() itself is not implemented in Python. That's up to the implementer.

    @MojoVampire
    Copy link
    Mannequin

    MojoVampire mannequin commented Sep 8, 2017

    I'd be -1 on this without a demonstrated broad need for this in at least some context outside of microbenchmarking utilities (which presumably have already implemented similar stuff).

    If a minimum bar for applicability isn't applied, we'll end up with dozens of these special purpose managers justified by the last limited applicability one. Stuff like contextlib.closing is justifiable (though I wish it allowed you to replace the method name called, so it could call terminate, kill, release, what-have-you) since cleanup close is so common, but disabling and reenabling gc is usually for timing purposes, and there aren't *that* many tools that need it.

    It doesn't seem all that useful for real time purposes either; sure, it disables gc, but it doesn't disable other forms of implicit non-local code execution that are surprisingly hard to predict (e.g. object destruction, including __del__, for non-cyclic cases is going to depend on whether the stuff being decref-ed is still owned outside the block). Disabling GC means a lot in Java, because *all* cleanup is GC; in Python, it's just cycle collection, so you're not giving much in the way of guarantees, as the code in question has to be written with a *lot* of assumptions that Python usually can't support (it's hardly a realtime language).

    Seems like if you want a speed up and reliability for this case (and all other context managers intended to be low overhead), it would be better to move parts of contextlib to the C layer (e.g. contextmanager and the classes it's implemented in terms of), so the simple and correct throwaway implementations for arbitrary custom use cases are fast enough; atomicity clearly doesn't actually matter here (it can't be made atomic in any meaningful sense given the lack of thread safety), so any real problem with the provided implementations (assuming they had try/finally added to make them robust) is overhead, not atomicity; the code posted so far would be fine (after adding try/finally) without the speed issues.

    @ncoghlan
    Copy link
    Contributor

    ncoghlan commented Sep 8, 2017

    This is being proposed for the gc module, not contextlib, so I'm not sure how the previous comment applies.

    This is just a convenience API for folks already doing this kind of manipulation themselves.

    @rhettinger
    Copy link
    Contributor Author

    Assigning this to Lisa for a C implementation, docs, and tests.

    @pablogsal
    Copy link
    Member

    I have prepared a PR in GitHub with an initial implementation of the context manager trying to fulfil the discussed requirements: #3980

    @pablogsal
    Copy link
    Member

    I just realize that the link I provided is incorrect. This is the correct one (also is the one that appears in this issue anyway):

    #4224

    @serhiy-storchaka
    Copy link
    Member

    What is the name of the context manager? gc_disabled, disabled, or Disabled? I see different names in the PR and this confuses me.

    @pablogsal
    Copy link
    Member

    Sorry about that. The context manager is "gc.Disabled()", which I admit is probably a bad name. The documentation is an example of the "equivalent" Python code as stated by Raymond in the first comment but I see now that this will raise confusion. Please, can you indicate what will be a correct name for the context manager so I can update the PR?

    @pablogsal
    Copy link
    Member

    Just to clarify the current situation: At this point, the contextmanager is referred as "disabled" in the C code but is exported as "Disabled" to the garbage collection module. The "gc_disabled" is the Python "equivalent" given by Raymond that is included in the documentation

    @ncoghlan
    Copy link
    Contributor

    Given the existing "gc.enable", "gc.disable" and "gc.isenabled" APIs, I'd suggest calling this one "gc.ensure_disabled": it ensures the GC is disabled in the with statement body, but only turns it back on at the end if it was previously enabled.

    That same name would then be used all the way through the code and documentation.

    @rhettinger
    Copy link
    Contributor Author

    New changeset 72a0d21 by Raymond Hettinger (Pablo Galindo) in branch 'master':
    bpo-31356: Add context manager to temporarily disable GC (GH-4224)
    72a0d21

    @1st1
    Copy link
    Member

    1st1 commented Jan 30, 2018

    A bug found by coverity:

    (PyErr_WarnEx might error out; please update the code to handle that)

    ________________________________________________________________________________________________________ *** CID 1428756: Error handling issues (CHECKED_RETURN)
    /Modules/gcmodule.c: 1071 in gc_enable_impl()
    1065
    1066 static PyObject *
    1067 gc_enable_impl(PyObject *module)
    1068 /[clinic end generated code: output=45a427e9dce9155c input=81ac4940ca579707]/
    1069 {
    1070 if(_PyRuntime.gc.disabled_threads){
    1071 PyErr_WarnEx(PyExc_RuntimeWarning, "Garbage collector enabled while another "
    1072 "thread is inside gc.ensure_enabled",1);
    1073 }
    1074 _PyRuntime.gc.enabled = 1;
    1075 Py_RETURN_NONE;
    1076 }

    @1st1 1st1 reopened this Jan 30, 2018
    @rhettinger
    Copy link
    Contributor Author

    (PyErr_WarnEx might error out; please update the code to handle that)

    Lisa, would you like to take a crack at fixing this one?

    @lisroach
    Copy link
    Contributor

    I gave it a shot- looks like we need to ensure that we catch any errors that could be thrown by the warning itself.

    I wasn't entirely sure how to create a test for this, if anyone knows how I'll definitely add it!

    @pablogsal
    Copy link
    Member

    @lisroach A possible test for this is repeat test_ensure_disabled_thread with warnings as errors:

    warnings.filterwarnings('error')

    and then checking for a RuntimeWarning exception instead of the warning. I think this will work because without the changes in this PR, this proposed test will produce this error:

    ======================================================================
    ERROR: test_ensure_disabled_thread (Lib.test.test_gc.GCTogglingTests)
    ----------------------------------------------------------------------
    RuntimeWarning: Garbage collector enabled while another thread is inside gc.ensure_enabled
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "/home/pgalindo3/cpython/Lib/test/support/__init__.py", line 2083, in decorator
        return func(*args)
      File "/home/pgalindo3/cpython/Lib/test/test_gc.py", line 1063, in test_ensure_disabled_thread
        inside_status_after_thread = gc.isenabled()
    SystemError: <built-in method __exit__ of gc.ensure_disabled object at 0x7f0253d22de0> returned a result with an error se

    Another posible test is checking that SystemError is not raised / in stderr.

    @serhiy-storchaka
    Copy link
    Member

    Actually raising an exception in PyErr_WarnEx() is not an error, but a standard behavior with corresponding configuration.

    For now running tests with -We in debug build crashes.

    $ ./python -We -m test test_gc
    Run tests sequentially
    0:00:00 load avg: 0.33 [1/1] test_gc
    Fatal Python error: a function returned a result with an error set
    RuntimeWarning: Garbage collector enabled while another thread is inside gc.ensure_enabled
    The above exception was the direct cause of the following exception:

    SystemError: <built-in method __exit__ of gc.ensure_disabled object at 0x7fb1b62a08f8> returned a result with an error set

    Thread 0x00007fb1b1773700 (most recent call first):
    File "/home/serhiy/py/cpython/Lib/test/test_gc.py", line 1050 in disabling_thread
    File "/home/serhiy/py/cpython/Lib/threading.py", line 865 in run
    File "/home/serhiy/py/cpython/Lib/threading.py", line 917 in _bootstrap_inner
    File "/home/serhiy/py/cpython/Lib/threading.py", line 885 in _bootstrap

    Current thread 0x00007fb1b824f040 (most recent call first):
    File "/home/serhiy/py/cpython/Lib/test/test_gc.py", line 1061 in test_ensure_disabled_thread
    File "/home/serhiy/py/cpython/Lib/test/support/init.py", line 2083 in decorator
    File "/home/serhiy/py/cpython/Lib/unittest/case.py", line 615 in run
    File "/home/serhiy/py/cpython/Lib/unittest/case.py", line 663 in __call__
    File "/home/serhiy/py/cpython/Lib/unittest/suite.py", line 122 in run
    File "/home/serhiy/py/cpython/Lib/unittest/suite.py", line 84 in __call__
    File "/home/serhiy/py/cpython/Lib/unittest/suite.py", line 122 in run
    File "/home/serhiy/py/cpython/Lib/unittest/suite.py", line 84 in __call__
    File "/home/serhiy/py/cpython/Lib/test/support/init.py", line 1760 in run
    File "/home/serhiy/py/cpython/Lib/test/support/init.py", line 1861 in _run_suite
    File "/home/serhiy/py/cpython/Lib/test/support/init.py", line 1951 in run_unittest
    File "/home/serhiy/py/cpython/Lib/test/test_gc.py", line 1088 in test_main
    File "/home/serhiy/py/cpython/Lib/test/libregrtest/runtest.py", line 176 in runtest_inner
    File "/home/serhiy/py/cpython/Lib/test/libregrtest/runtest.py", line 140 in runtest
    File "/home/serhiy/py/cpython/Lib/test/libregrtest/main.py", line 379 in run_tests_sequential
    File "/home/serhiy/py/cpython/Lib/test/libregrtest/main.py", line 458 in run_tests
    File "/home/serhiy/py/cpython/Lib/test/libregrtest/main.py", line 536 in _main
    File "/home/serhiy/py/cpython/Lib/test/libregrtest/main.py", line 510 in main
    File "/home/serhiy/py/cpython/Lib/test/libregrtest/main.py", line 585 in main
    File "/home/serhiy/py/cpython/Lib/test/main.py", line 2 in <module>
    File "/home/serhiy/py/cpython/Lib/runpy.py", line 85 in _run_code
    File "/home/serhiy/py/cpython/Lib/runpy.py", line 193 in _run_module_as_main
    Aborted (core dumped)

    @1st1 1st1 closed this as completed Feb 2, 2018
    @gpshead
    Copy link
    Member

    gpshead commented Feb 2, 2018

    The idea which this issue represents is not rejected. It is a good one, we found a need for it during the dev sprint last September.

    @gpshead gpshead added 3.8 only security fixes and removed 3.7 (EOL) end of life labels Feb 2, 2018
    @gpshead gpshead reopened this Feb 2, 2018
    @1st1
    Copy link
    Member

    1st1 commented Feb 2, 2018

    The idea which this issue represents is not rejected. It is a good one, we found a need for it during the dev sprint last September.

    Well, not everybody thinks it is a good one. I, for instance, don't think it's a good idea, so it is at least one "-1". I saw Serhiy was unsure about this new feature too, so maybe there are two "-1"s; I don't know. So I kindly ask(-ed) for it to be openly discussed on python-dev, instead of making a unilateral decision.

    The problem with the current design is that GC can become enabled inside the 'with' block at any time:

        with gc.ensure_disabled():
            # gc.is_enabled() might be True !

    The GC can become enabled from another OS thread, as we have one GC per process. Adding a locking mechanism might be tricky in terms of implementation, and risky in terms of allowing people to accidentally have a deadlock or something. In short, I don't see any way to make this context manager to work reliably in CPython.

    Therefore, I think that the best location for a helper like this would be some unittesting helpers collection, as it can work only under some very specific conditions. The core 'gc' module is currently a collection of low-level primitives. I think we need a very solid motivation to add a core GC function that works unreliably and is suitable only for unittesting (at best).

    Maybe I'm completely wrong here, in which case I would love to be proved wrong and not just ignored.

    @serhiy-storchaka
    Copy link
    Member

    I concur with Yury in every point.

    The idea looks good for three core developers, but I just don't understand this. This feature looks useless and misleading to me. It is not atomic and doesn't ensure anything, despite its name. If it will be added in the stdlib, there should be very good explanation of its purpose and limitations in the documentation. And I agree that unittest may be better place than gc if the purpose of it is testing.

    @pitrou
    Copy link
    Member

    pitrou commented Feb 2, 2018

    Indeed if unit testing is the main use case, I don't really see the point of adding C code. People can code a simple helper using contextlib.contextmanager in a couple of lines.

    @gpshead
    Copy link
    Member

    gpshead commented Feb 3, 2018

    Nick and Raymond: do you remember what our original motivating use cases were for this idea during the sprint?

    @ncoghlan
    Copy link
    Contributor

    ncoghlan commented Feb 5, 2018

    If I recall the discussion correctly, it was:

    1. That this was worth doing precisely because the naive approach is likely to be broken in the presence of multiple threads;
    2. It was only worth doing either as a true global disable that accounted for multi-threading (e.g. backed by a counted semaphore or the functional equivalent), or else by making gc enable/disable status have a thread local toggle in addition to the global one (so the context manager can ensure "GC is off *in this thread*, regardless of the global status").

    Either of those two options requires changes to the main GC machinery though, as otherwise you basically *can't* write a correct context manager for this use case, since a direct call to gc.enable() in another thread would always be problematic.

    @serhiy-storchaka
    Copy link
    Member

    1. The used approach was broken in the presence of multiple threads too. It didn't guarantee even that GC will be disabled in the next line.

    2. What is a sense of disabling GC in a single thread? Objects in Python are not thread local, they are accessible from all threads, and collecting garbage in one thread affects other threads.

    For truly disabling GC globally you need to use a counted semaphore or other synchronization primitives, and this can be implemented at Python level. But what are use cases for this context manager? Isn't naive approach enough?

    @sweeneyde
    Copy link
    Member

    https://bugs.python.org/issue41545 is a duplicate of this.

    In that report, there's an example of something that can go wrong with the save-a-boolean-per-context-manager approach even when threads are not used, but when concurrent generators are used, like

    def gen():
        with gc_disabled():
            yield 1
            yield 2
            yield 3
    
    a = gen()
    b = gen()
    next(a) # disable gc
    next(b) 
    list(a) # this re-enableds the gc
    next(b) # gc is enabled but shouldn't be.

    A counter for "number of times disabled" may be a better approach.

    @bharel
    Copy link
    Mannequin

    bharel mannequin commented Jan 18, 2021

    I've taken a shot making this in pure Python, and took into account a few more factors such as starvation and reentrancy.

    As Nick said, one of the only ways it can truly work is if it's completely global, in which case we don't need to use the internal lock and relying on the GIL would work.

    It's not very efficient atm, as the overhead of the Lock() and
    resulting python code probably offsets the benefit of disabling the GC, but it can be fine for some uses I guess.

    https://github.com/bharel/disable_gc

    I'll release it to pypi sometime soon and we can take a look at the not-so-accurate usage metric to see if such a thing is needed in the standard library.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @iritkatriel iritkatriel added 3.12 bugs and security fixes and removed 3.8 only security fixes labels Sep 25, 2022
    @iritkatriel iritkatriel added pending The issue will be closed if no feedback is provided and removed 3.12 bugs and security fixes labels May 20, 2023
    @iritkatriel
    Copy link
    Member

    iritkatriel commented May 20, 2023

    The discussion shows there is no consensus on adding this feature. Marking as pending with a view to closing this (unless someone objects).

    @rhettinger
    Copy link
    Contributor Author

    I don't think "non-consensus" is a fair reading. We made an agreed to commit, but reverted it only because there was a minor issue with it. The issue is stale because no one has worked on fixing it, but it is still valid.

    The proposal would work fine unless called in multiple threads, so it would need to be documented as not being threadsafe. It is no more or less powerful that the current way we do it with a try/finally. This would just be a nicer spelling than what we currently have. This doesn't matter to most users since most people don't use enable/disable at all, but it does matter to those are trying to control real-time behavior or those trying to limit reentrancy. Temporarily turning off GC is one of the few tools available to mitigate the risk of a potentially expensive collection or a collection that triggers reentrant code. Those users deserve to have the cleaner call afforded by the with statement.

    @iritkatriel
    Copy link
    Member

    There were -1s from @1st1 and @serhiy-storchaka, which I interpreted as non-consensus.

    @ncoghlan wrote that there's no point in doing this unless it's done in a thread-safe way.

    @pitrou
    Copy link
    Member

    pitrou commented May 22, 2023

    I do think this would have a value if implemented in a thread-safe way, therefore this issue could probably be kept open.

    @iritkatriel iritkatriel removed the pending The issue will be closed if no feedback is provided label May 22, 2023
    @rhettinger
    Copy link
    Contributor Author

    rhettinger commented May 22, 2023

    It may be useful to compare the proposal to contextlib.chdir() which has a similar motivation is not threadsafe. All we're looking for is a better way to spell the code that is currently used in practice.

    FWIW, there are reasons that people use a try/finally around disable/enable. First, there doesn't seem to be a reasonable alternative because the use oflocks has its complications and perils as well. Second, the applications for disable/enable tend to be tolerant of an occassional premature enable() call. This is mostly because even with gc disabled, it is very difficult to provide real time guarantees in Python. Disabling GC is a mitigation, not a guarantee. Also, even if another thread reenables GC, it doesn't mean that a collection will happen immediately.

    @gpshead
    Copy link
    Member

    gpshead commented May 23, 2023

    the applications for disable/enable tend to be tolerant of an occassional premature enable() call. This is mostly because even with gc disabled, it is very difficult to provide real time guarantees in Python. Disabling GC is a mitigation, not a guarantee. Also, even if another thread reenables GC, it doesn't mean that a collection will happen immediately.

    I mostly agreed with the sentiments in that selective quote. If we were to expand the gc API we need to make these expectations (really "don't expect any of this to reliably ever do what you want") clear in our gc module docs.

    The difference between contextlib.chdir and this for gc is that I view a chdir as a more common operation - useful for little scripts. While I view the gc module as something that probably should've been named _gc and is something no user code should ever use. It is an implementation detail, using it is always a code smell.

    Adding a context managing variant of gc.disable() could be interpreted as blessing the concept as a solution to someones problems. When nothing done with the gc module ever is.

    That leaves me as -0 on bothering with this even though I'd have found the idea convenient in some tests. Even when I would've reached for it, it was probably still the wrong tool.

    @carljm
    Copy link
    Member

    carljm commented May 23, 2023

    While I view the gc module as something that probably should've been named _gc and is something no user code should ever use. It is an implementation detail, using it is always a code smell.

    This may be getting OT for this issue, but given how important GC threshold tuning (including, in some cases, disabling automatic GC and only calling gc.collect() at certain well-chosen points) can be to Python performance, and how dependent the correct tuning is on the specific characteristics of the workload, and how bad (orders of magnitude too low) the current default thresholds are for many Python workloads, I don't think we can really currently support the idea that use of the gc module is always a code smell and no user code should ever use it. I've personally improved the performance of Python workloads by over 30% solely by tuning the GC using APIs in the gc module; I'd find it hard to accept that that's something I should not have done.

    @gpshead
    Copy link
    Member

    gpshead commented May 23, 2023

    I'm channeling my ideal world of perfectly spherical theoretical python applications and implementations there... YouTube did similar gc tweaking.

    @carljm
    Copy link
    Member

    carljm commented May 23, 2023

    I agree, in the ideal world of perfectly spherical Python, the GC would be so fast and so perfectly self-tuning that no user code would ever have reason to touch it!

    @pitrou
    Copy link
    Member

    pitrou commented May 23, 2023

    First, there doesn't seem to be a reasonable alternative because the use oflocks has its complications and perils as well. Second, the applications for disable/enable tend to be tolerant of an occassional premature enable() call. This is mostly because even with gc disabled, it is very difficult to provide real time guarantees in Python. Disabling GC is a mitigation, not a guarantee.

    I'm not sure what you're alluding to here. Perhaps we're having a different model of when people might want to selectively disable the GC? My experience is that - apart from uncommon unit tests - the desire to disable the GC comes when particular performance issues are encountered on long-running applications with a large resident working set and very dynamic allocation spikes. Those applications have a high likelihood of being multi-threaded.

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests