Skip to content

Commit a94f4e7

Browse files
committed
gh-148587: Pre-size and short-circuit empty in lazy modules snapshot
Pre-size the temporary dict in _PyImport_GetLazyModulesSnapshot via _PyDict_NewPresized to avoid resizes during the inline copy. Add a fast path that returns an empty frozendict directly when the registry has no entries, skipping the temporary dict allocation entirely.
1 parent f4f8fb2 commit a94f4e7

1 file changed

Lines changed: 27 additions & 17 deletions

File tree

Python/import.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -290,34 +290,44 @@ _PyImport_GetLazyModulesSnapshot(PyInterpreterState *interp)
290290
return PyFrozenDict_New(NULL);
291291
}
292292

293-
PyObject *tmp = PyDict_New();
294-
if (tmp == NULL) {
295-
return NULL;
296-
}
297-
293+
PyObject *tmp = NULL;
298294
int err = 0;
295+
299296
Py_BEGIN_CRITICAL_SECTION(lazy_modules);
300-
Py_ssize_t pos = 0;
301-
PyObject *key, *value;
302-
while (PyDict_Next(lazy_modules, &pos, &key, &value)) {
303-
PyObject *frozen = PyFrozenSet_New(value);
304-
if (frozen == NULL) {
297+
Py_ssize_t size = PyDict_GET_SIZE(lazy_modules);
298+
if (size > 0) {
299+
tmp = _PyDict_NewPresized(size);
300+
if (tmp == NULL) {
305301
err = -1;
306-
break;
307302
}
308-
if (PyDict_SetItem(tmp, key, frozen) < 0) {
309-
Py_DECREF(frozen);
310-
err = -1;
311-
break;
303+
else {
304+
Py_ssize_t pos = 0;
305+
PyObject *key, *value;
306+
while (PyDict_Next(lazy_modules, &pos, &key, &value)) {
307+
PyObject *frozen = PyFrozenSet_New(value);
308+
if (frozen == NULL) {
309+
err = -1;
310+
break;
311+
}
312+
if (PyDict_SetItem(tmp, key, frozen) < 0) {
313+
Py_DECREF(frozen);
314+
err = -1;
315+
break;
316+
}
317+
Py_DECREF(frozen);
318+
}
312319
}
313-
Py_DECREF(frozen);
314320
}
315321
Py_END_CRITICAL_SECTION();
316322

317323
if (err < 0) {
318-
Py_DECREF(tmp);
324+
Py_XDECREF(tmp);
319325
return NULL;
320326
}
327+
if (tmp == NULL) {
328+
// Registry is empty.
329+
return PyFrozenDict_New(NULL);
330+
}
321331

322332
PyObject *snapshot = PyFrozenDict_New(tmp);
323333
Py_DECREF(tmp);

0 commit comments

Comments
 (0)