diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-11-16-51-51.gh-issue-153568.ast2objgc.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-11-16-51-51.gh-issue-153568.ast2objgc.rst new file mode 100644 index 000000000000000..b7d413d422994ff --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-11-16-51-51.gh-issue-153568.ast2objgc.rst @@ -0,0 +1,2 @@ +Speed up :func:`ast.parse` by pausing the garbage collector while the AST is +converted to Python objects. diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index d53886866f54f86..2edd3cb4718e893 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -2117,7 +2117,20 @@ class PartingShots(StaticVisitor): if (state == NULL) { return NULL; } +#ifndef Py_GIL_DISABLED + // Freshly converted AST nodes cannot be part of a reference cycle yet, + // so a garbage collection while building them cannot free anything of + // this tree and only pays to traverse its half-built nodes. Pause the + // collector while the conversion runs. PyGC_Disable() is interpreter-wide, + // so this optimization is not safe in a free-threaded build. + int gc_was_enabled = PyGC_Disable(); +#endif PyObject *result = ast2obj_mod(state, t); +#ifndef Py_GIL_DISABLED + if (gc_was_enabled) { + PyGC_Enable(); + } +#endif return result; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index f36072dfce098c6..e501461fcc79cea 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -18544,7 +18544,20 @@ PyObject* PyAST_mod2obj(mod_ty t) if (state == NULL) { return NULL; } +#ifndef Py_GIL_DISABLED + // Freshly converted AST nodes cannot be part of a reference cycle yet, + // so a garbage collection while building them cannot free anything of + // this tree and only pays to traverse its half-built nodes. Pause the + // collector while the conversion runs. PyGC_Disable() is interpreter-wide, + // so this optimization is not safe in a free-threaded build. + int gc_was_enabled = PyGC_Disable(); +#endif PyObject *result = ast2obj_mod(state, t); +#ifndef Py_GIL_DISABLED + if (gc_was_enabled) { + PyGC_Enable(); + } +#endif return result; }