mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
[3.14] GH-139951: Fix major GC performance regression. Backport of GH-140262 (GH-140447)
* Count number of actually tracked objects, instead of trackable objects. This ensures that untracking tuples has the desired effect of reducing GC overhead * Do not track most untrackable tuples during creation. This prevents large numbers of small tuples causing execessive GCs.
This commit is contained in:
parent
0fdae5f590
commit
d1a434f7b2
5 changed files with 94 additions and 36 deletions
|
|
@ -156,6 +156,18 @@ _PyTuple_MaybeUntrack(PyObject *op)
|
|||
_PyObject_GC_UNTRACK(op);
|
||||
}
|
||||
|
||||
/* Fast, but conservative check if an object maybe tracked
|
||||
May return true for an object that is not tracked,
|
||||
Will always return true for an object that is tracked.
|
||||
This is a temporary workaround until _PyObject_GC_IS_TRACKED
|
||||
becomes fast and safe to call on non-GC objects.
|
||||
*/
|
||||
static bool
|
||||
maybe_tracked(PyObject *ob)
|
||||
{
|
||||
return _PyType_IS_GC(Py_TYPE(ob));
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyTuple_Pack(Py_ssize_t n, ...)
|
||||
{
|
||||
|
|
@ -163,6 +175,7 @@ PyTuple_Pack(Py_ssize_t n, ...)
|
|||
PyObject *o;
|
||||
PyObject **items;
|
||||
va_list vargs;
|
||||
bool track = false;
|
||||
|
||||
if (n == 0) {
|
||||
return tuple_get_empty();
|
||||
|
|
@ -177,10 +190,15 @@ PyTuple_Pack(Py_ssize_t n, ...)
|
|||
items = result->ob_item;
|
||||
for (i = 0; i < n; i++) {
|
||||
o = va_arg(vargs, PyObject *);
|
||||
if (!track && maybe_tracked(o)) {
|
||||
track = true;
|
||||
}
|
||||
items[i] = Py_NewRef(o);
|
||||
}
|
||||
va_end(vargs);
|
||||
_PyObject_GC_TRACK(result);
|
||||
if (track) {
|
||||
_PyObject_GC_TRACK(result);
|
||||
}
|
||||
return (PyObject *)result;
|
||||
}
|
||||
|
||||
|
|
@ -377,11 +395,17 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
|
|||
return NULL;
|
||||
}
|
||||
PyObject **dst = tuple->ob_item;
|
||||
bool track = false;
|
||||
for (Py_ssize_t i = 0; i < n; i++) {
|
||||
PyObject *item = src[i];
|
||||
if (!track && maybe_tracked(item)) {
|
||||
track = true;
|
||||
}
|
||||
dst[i] = Py_NewRef(item);
|
||||
}
|
||||
_PyObject_GC_TRACK(tuple);
|
||||
if (track) {
|
||||
_PyObject_GC_TRACK(tuple);
|
||||
}
|
||||
return (PyObject *)tuple;
|
||||
}
|
||||
|
||||
|
|
@ -396,10 +420,17 @@ _PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
|
|||
return NULL;
|
||||
}
|
||||
PyObject **dst = tuple->ob_item;
|
||||
bool track = false;
|
||||
for (Py_ssize_t i = 0; i < n; i++) {
|
||||
dst[i] = PyStackRef_AsPyObjectSteal(src[i]);
|
||||
PyObject *item = PyStackRef_AsPyObjectSteal(src[i]);
|
||||
if (!track && maybe_tracked(item)) {
|
||||
track = true;
|
||||
}
|
||||
dst[i] = item;
|
||||
}
|
||||
if (track) {
|
||||
_PyObject_GC_TRACK(tuple);
|
||||
}
|
||||
_PyObject_GC_TRACK(tuple);
|
||||
return (PyObject *)tuple;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue