Skip to content

Commit 4e00e25

Browse files
authored
gh-129813, PEP 782: Add PyBytesWriter.overallocate (#138941)
Disable overallocation in _PyBytes_FormatEx() at the last write.
1 parent 4554486 commit 4e00e25

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

Include/internal/pycore_bytesobject.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ PyAPI_FUNC(void*) _PyBytesWriter_WriteBytes(_PyBytesWriter *writer,
147147
PyAPI_FUNC(PyBytesWriter*) _PyBytesWriter_CreateByteArray(
148148
Py_ssize_t size);
149149

150+
151+
struct PyBytesWriter {
152+
char small_buffer[256];
153+
PyObject *obj;
154+
Py_ssize_t size;
155+
int use_bytearray;
156+
int overallocate;
157+
};
158+
150159
#ifdef __cplusplus
151160
}
152161
#endif

Objects/bytesobject.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,11 @@ _PyBytes_FormatEx(const char *format, Py_ssize_t format_len,
836836
if (v == NULL)
837837
goto error;
838838

839+
if (fmtcnt == 0) {
840+
/* last write: disable writer overallocation */
841+
writer->overallocate = 0;
842+
}
843+
839844
sign = 0;
840845
fill = ' ';
841846
switch (c) {
@@ -1056,6 +1061,10 @@ _PyBytes_FormatEx(const char *format, Py_ssize_t format_len,
10561061
assert((res - before) == alloc);
10571062
#endif
10581063
} /* '%' */
1064+
1065+
/* If overallocation was disabled, ensure that it was the last
1066+
write. Otherwise, we missed an optimization */
1067+
assert(writer->overallocate || fmtcnt == 0 || use_bytearray);
10591068
} /* until end */
10601069

10611070
if (argidx < arglen && !dict) {
@@ -3746,14 +3755,6 @@ _PyBytes_Repeat(char* dest, Py_ssize_t len_dest,
37463755

37473756
// --- PyBytesWriter API -----------------------------------------------------
37483757

3749-
struct PyBytesWriter {
3750-
char small_buffer[256];
3751-
PyObject *obj;
3752-
Py_ssize_t size;
3753-
int use_bytearray;
3754-
};
3755-
3756-
37573758
static inline char*
37583759
byteswriter_data(PyBytesWriter *writer)
37593760
{
@@ -3802,7 +3803,8 @@ byteswriter_resize(PyBytesWriter *writer, Py_ssize_t size, int overallocate)
38023803
return 0;
38033804
}
38043805

3805-
if (overallocate && !writer->use_bytearray) {
3806+
overallocate &= writer->overallocate;
3807+
if (overallocate) {
38063808
if (size <= (PY_SSIZE_T_MAX - size / OVERALLOCATE_FACTOR)) {
38073809
size += size / OVERALLOCATE_FACTOR;
38083810
}
@@ -3867,6 +3869,7 @@ byteswriter_create(Py_ssize_t size, int use_bytearray)
38673869
writer->obj = NULL;
38683870
writer->size = 0;
38693871
writer->use_bytearray = use_bytearray;
3872+
writer->overallocate = !use_bytearray;
38703873

38713874
if (size >= 1) {
38723875
if (byteswriter_resize(writer, size, 0) < 0) {

0 commit comments

Comments
 (0)