Repository navigation
Streamline list.append for the common case #91165
Description
Activity
list_resize is a long function that probably won't get inlined. But for the vast majority of cases in list.append, we just need to check whether the list is big enough (not whether it's small enough, or whether it's null or the wrong type), then insert and update the size. This can be inlined, with an actual call only taking place whenever we need to resize.
We can also add a reference-consuming version of PyList_Append to elide an INCREF/DECREF pair.
- added3.11only security fixesonly security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)performancePerformance or resource usagePerformance or resource usage
on Mar 14, 2022 Hmm. Would you measure benefit from inlining and skipping incref/decref separately?
If benefit of inlining is very small, making _PyList_AppendTakeRef() as regular internal API looks better to me.
The attached _PyList_AppendTakeRef.diff has the ceval.c, but this implementation:
int _PyList_AppendTakeRef(PyListObject *self, PyObject *newitem) { assert(self != NULL && newitem != NULL); assert(PyList_Check(self)); Py_ssize_t len = PyList_GET_SIZE(self); Py_ssize_t allocated = self->allocated; assert((size_t)len + 1 < PY_SSIZE_T_MAX); if (allocated > len) { PyList_SET_ITEM(self, len, newitem); Py_SET_SIZE(self, len + 1); return 0; } if (list_resize(self, len + 1) < 0) { Py_DECREF(newitem); return -1; } PyList_SET_ITEM(self, len, newitem); return 0; }
Results:
Benchmark main PR 31864 _PyList_AppendTakeRef.diff listcomp 100 1.61 us 1.33 us: 1.21x faster 1.55 us: 1.04x faster append 100 2.11 us 1.82 us: 1.15x faster 2.05 us: 1.03x faster listcomp 1000 12.6 us 9.83 us: 1.28x faster 11.9 us: 1.06x faster append 1000 18.1 us 15.3 us: 1.18x faster 17.6 us: 1.03x faster listcomp 10000 121 us 93.2 us: 1.29x faster 114 us: 1.06x faster append 10000 175 us 150 us: 1.17x faster 172 us: 1.02x faster listcomp 100000 1.17 ms 923 us: 1.26x faster 1.15 ms: 1.02x faster append 100000 1.70 ms 1.49 ms: 1.14x faster not significant Geometric mean (ref) 1.21x faster 1.03x faster Thank you. I agree that inlining is worth enough.
But we already inlined too many functions in ceval and there is an issue caused by it... (bpo-45116)
Buildbots are passing, so I'm closing this. Thanks for the catch and fix!
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: