mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	[3.13] GH-117759: Document incremental GC (GH-123266) (#123395)
GH-117759: Document incremental GC (GH-123266)
* Update what's new
* Update gc module docs and fix inconsistency in gc.get_objects
(cherry picked from commit f49a91648a)
Co-authored-by: Mark Shannon <mark@hotpy.org>
			
			
This commit is contained in:
		
							parent
							
								
									cbcb9e1c0f
								
							
						
					
					
						commit
						aca65112fe
					
				
					 3 changed files with 69 additions and 26 deletions
				
			
		| 
						 | 
					@ -40,11 +40,18 @@ The :mod:`gc` module provides the following functions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. function:: collect(generation=2)
 | 
					.. function:: collect(generation=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   With no arguments, run a full collection.  The optional argument *generation*
 | 
					   Perform a collection.  The optional argument *generation*
 | 
				
			||||||
   may be an integer specifying which generation to collect (from 0 to 2).  A
 | 
					   may be an integer specifying which generation to collect (from 0 to 2).  A
 | 
				
			||||||
   :exc:`ValueError` is raised if the generation number is invalid. The sum of
 | 
					   :exc:`ValueError` is raised if the generation number is invalid. The sum of
 | 
				
			||||||
   collected objects and uncollectable objects is returned.
 | 
					   collected objects and uncollectable objects is returned.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Calling ``gc.collect(0)`` will perform a GC collection on the young generation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Calling ``gc.collect(1)`` will perform a GC collection on the young generation
 | 
				
			||||||
 | 
					   and an increment of the old generation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Calling ``gc.collect(2)`` or ``gc.collect()`` performs a full collection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   The free lists maintained for a number of built-in types are cleared
 | 
					   The free lists maintained for a number of built-in types are cleared
 | 
				
			||||||
   whenever a full collection or collection of the highest generation (2)
 | 
					   whenever a full collection or collection of the highest generation (2)
 | 
				
			||||||
   is run.  Not all items in some free lists may be freed due to the
 | 
					   is run.  Not all items in some free lists may be freed due to the
 | 
				
			||||||
| 
						 | 
					@ -53,6 +60,9 @@ The :mod:`gc` module provides the following functions:
 | 
				
			||||||
   The effect of calling ``gc.collect()`` while the interpreter is already
 | 
					   The effect of calling ``gc.collect()`` while the interpreter is already
 | 
				
			||||||
   performing a collection is undefined.
 | 
					   performing a collection is undefined.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   .. versionchanged:: 3.13
 | 
				
			||||||
 | 
					      ``generation=1`` performs an increment of collection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. function:: set_debug(flags)
 | 
					.. function:: set_debug(flags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,13 +78,20 @@ The :mod:`gc` module provides the following functions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. function:: get_objects(generation=None)
 | 
					.. function:: get_objects(generation=None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   Returns a list of all objects tracked by the collector, excluding the list
 | 
					   Returns a list of all objects tracked by the collector, excluding the list
 | 
				
			||||||
   returned. If *generation* is not ``None``, return only the objects tracked by
 | 
					   returned. If *generation* is not ``None``, return only the objects as follows:
 | 
				
			||||||
   the collector that are in that generation.
 | 
					
 | 
				
			||||||
 | 
					   * 0: All objects in the young generation
 | 
				
			||||||
 | 
					   * 1: No objects, as there is no generation 1 (as of Python 3.13)
 | 
				
			||||||
 | 
					   * 2: All objects in the old generation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   .. versionchanged:: 3.8
 | 
					   .. versionchanged:: 3.8
 | 
				
			||||||
      New *generation* parameter.
 | 
					      New *generation* parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   .. versionchanged:: 3.13
 | 
				
			||||||
 | 
					      Generation 1 is removed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   .. audit-event:: gc.get_objects generation gc.get_objects
 | 
					   .. audit-event:: gc.get_objects generation gc.get_objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. function:: get_stats()
 | 
					.. function:: get_stats()
 | 
				
			||||||
| 
						 | 
					@ -101,19 +118,27 @@ The :mod:`gc` module provides the following functions:
 | 
				
			||||||
   Set the garbage collection thresholds (the collection frequency). Setting
 | 
					   Set the garbage collection thresholds (the collection frequency). Setting
 | 
				
			||||||
   *threshold0* to zero disables collection.
 | 
					   *threshold0* to zero disables collection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   The GC classifies objects into three generations depending on how many
 | 
					   The GC classifies objects into two generations depending on whether they have
 | 
				
			||||||
   collection sweeps they have survived.  New objects are placed in the youngest
 | 
					   survived a collection. New objects are placed in the young generation. If an
 | 
				
			||||||
   generation (generation ``0``).  If an object survives a collection it is moved
 | 
					   object survives a collection it is moved into the old generation.
 | 
				
			||||||
   into the next older generation.  Since generation ``2`` is the oldest
 | 
					
 | 
				
			||||||
   generation, objects in that generation remain there after a collection.  In
 | 
					   In order to decide when to run, the collector keeps track of the number of object
 | 
				
			||||||
   order to decide when to run, the collector keeps track of the number object
 | 
					 | 
				
			||||||
   allocations and deallocations since the last collection.  When the number of
 | 
					   allocations and deallocations since the last collection.  When the number of
 | 
				
			||||||
   allocations minus the number of deallocations exceeds *threshold0*, collection
 | 
					   allocations minus the number of deallocations exceeds *threshold0*, collection
 | 
				
			||||||
   starts.  Initially only generation ``0`` is examined.  If generation ``0`` has
 | 
					   starts. For each collection, all the objects in the young generation and some
 | 
				
			||||||
   been examined more than *threshold1* times since generation ``1`` has been
 | 
					   fraction of the old generation is collected.
 | 
				
			||||||
   examined, then generation ``1`` is examined as well.
 | 
					
 | 
				
			||||||
   With the third generation, things are a bit more complicated,
 | 
					   The fraction of the old generation that is collected is **inversely** proportional
 | 
				
			||||||
   see `Collecting the oldest generation <https://devguide.python.org/garbage_collector/#collecting-the-oldest-generation>`_ for more information.
 | 
					   to *threshold1*. The larger *threshold1* is, the slower objects in the old generation
 | 
				
			||||||
 | 
					   are collected.
 | 
				
			||||||
 | 
					   For the default value of 10, 1% of the old generation is scanned during each collection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   *threshold2* is ignored.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   See `Garbage collector design <https://devguide.python.org/garbage_collector>`_ for more information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   .. versionchanged:: 3.13
 | 
				
			||||||
 | 
					      *threshold2* is ignored
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. function:: get_count()
 | 
					.. function:: get_count()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -495,6 +495,19 @@ Incremental garbage collection
 | 
				
			||||||
The cycle garbage collector is now incremental.
 | 
					The cycle garbage collector is now incremental.
 | 
				
			||||||
This means that maximum pause times are reduced
 | 
					This means that maximum pause times are reduced
 | 
				
			||||||
by an order of magnitude or more for larger heaps.
 | 
					by an order of magnitude or more for larger heaps.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are now only two generations: young and old.
 | 
				
			||||||
 | 
					When :func:`gc.collect` is not called directly, the
 | 
				
			||||||
 | 
					GC is invoked a little less frequently. When invoked, it
 | 
				
			||||||
 | 
					collects the young generation and an increment of the
 | 
				
			||||||
 | 
					old generation, instead of collecting one or more generations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The behavior of :func:`!gc.collect` changes slightly:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* ``gc.collect(1)``: Performs an increment of GC,
 | 
				
			||||||
 | 
					  rather than collecting generation 1.
 | 
				
			||||||
 | 
					* Other calls to :func:`!gc.collect` are unchanged.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(Contributed by Mark Shannon in :gh:`108362`.)
 | 
					(Contributed by Mark Shannon in :gh:`108362`.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								Python/gc.c
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								Python/gc.c
									
										
									
									
									
								
							| 
						 | 
					@ -1701,20 +1701,25 @@ _PyGC_GetObjects(PyInterpreterState *interp, int generation)
 | 
				
			||||||
    GCState *gcstate = &interp->gc;
 | 
					    GCState *gcstate = &interp->gc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PyObject *result = PyList_New(0);
 | 
					    PyObject *result = PyList_New(0);
 | 
				
			||||||
    if (result == NULL) {
 | 
					    /* Generation:
 | 
				
			||||||
        return NULL;
 | 
					     * -1: Return all objects
 | 
				
			||||||
 | 
					     * 0: All young objects
 | 
				
			||||||
 | 
					     * 1: No objects
 | 
				
			||||||
 | 
					     * 2: All old objects
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (result == NULL || generation == 1) {
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (generation <= 0) {
 | 
				
			||||||
    if (generation == -1) {
 | 
					        if (append_objects(result, &gcstate->young.head)) {
 | 
				
			||||||
        /* If generation is -1, get all objects from all generations */
 | 
					 | 
				
			||||||
        for (int i = 0; i < NUM_GENERATIONS; i++) {
 | 
					 | 
				
			||||||
            if (append_objects(result, GEN_HEAD(gcstate, i))) {
 | 
					 | 
				
			||||||
            goto error;
 | 
					            goto error;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (generation != 0) {
 | 
				
			||||||
 | 
					        if (append_objects(result, &gcstate->old[0].head)) {
 | 
				
			||||||
 | 
					            goto error;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    else {
 | 
					        if (append_objects(result, &gcstate->old[1].head)) {
 | 
				
			||||||
        if (append_objects(result, GEN_HEAD(gcstate, generation))) {
 | 
					 | 
				
			||||||
            goto error;
 | 
					            goto error;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue