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..f409f32e6313589 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -2117,7 +2117,15 @@ class PartingShots(StaticVisitor): if (state == NULL) { return NULL; } + // 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. + int gc_was_enabled = PyGC_Disable(); PyObject *result = ast2obj_mod(state, t); + if (gc_was_enabled) { + PyGC_Enable(); + } return result; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index f36072dfce098c6..aa1e5bc813b162f 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -18544,7 +18544,15 @@ PyObject* PyAST_mod2obj(mod_ty t) if (state == NULL) { return NULL; } + // 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. + int gc_was_enabled = PyGC_Disable(); PyObject *result = ast2obj_mod(state, t); + if (gc_was_enabled) { + PyGC_Enable(); + } return result; }