Skip to content

Commit c1553bc

Browse files
authored
gh-119182: Use public PyUnicodeWriter API in union_repr() (#120797)
The public PyUnicodeWriter API enables overallocation by default and so is more efficient. Benchmark: python -m pyperf timeit \ -s 't = int | float | complex | str | bytes | bytearray' \ ' | memoryview | list | dict' \ 'str(t)' Result: 1.29 us +- 0.02 us -> 1.00 us +- 0.02 us: 1.29x faster
1 parent 73b4492 commit c1553bc

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

Objects/unionobject.c

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,14 @@ _Py_union_type_or(PyObject* self, PyObject* other)
182182
}
183183

184184
static int
185-
union_repr_item(_PyUnicodeWriter *writer, PyObject *p)
185+
union_repr_item(PyUnicodeWriter *writer, PyObject *p)
186186
{
187187
PyObject *qualname = NULL;
188188
PyObject *module = NULL;
189-
PyObject *r = NULL;
190189
int rc;
191190

192191
if (p == (PyObject *)&_PyNone_Type) {
193-
return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4);
192+
return PyUnicodeWriter_WriteUTF8(writer, "None", 4);
194193
}
195194

196195
if ((rc = PyObject_HasAttrWithError(p, &_Py_ID(__origin__))) > 0 &&
@@ -200,17 +199,17 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p)
200199
goto use_repr;
201200
}
202201
if (rc < 0) {
203-
goto exit;
202+
goto error;
204203
}
205204

206205
if (PyObject_GetOptionalAttr(p, &_Py_ID(__qualname__), &qualname) < 0) {
207-
goto exit;
206+
goto error;
208207
}
209208
if (qualname == NULL) {
210209
goto use_repr;
211210
}
212211
if (PyObject_GetOptionalAttr(p, &_Py_ID(__module__), &module) < 0) {
213-
goto exit;
212+
goto error;
214213
}
215214
if (module == NULL || module == Py_None) {
216215
goto use_repr;
@@ -221,24 +220,25 @@ union_repr_item(_PyUnicodeWriter *writer, PyObject *p)
221220
_PyUnicode_EqualToASCIIString(module, "builtins"))
222221
{
223222
// builtins don't need a module name
224-
r = PyObject_Str(qualname);
225-
goto exit;
223+
rc = PyUnicodeWriter_WriteStr(writer, qualname);
224+
goto done;
226225
}
227226
else {
228-
r = PyUnicode_FromFormat("%S.%S", module, qualname);
229-
goto exit;
227+
rc = PyUnicodeWriter_Format(writer, "%S.%S", module, qualname);
228+
goto done;
230229
}
231230

231+
error:
232+
rc = -1;
233+
goto done;
234+
232235
use_repr:
233-
r = PyObject_Repr(p);
234-
exit:
236+
rc = PyUnicodeWriter_WriteRepr(writer, p);
237+
goto done;
238+
239+
done:
235240
Py_XDECREF(qualname);
236241
Py_XDECREF(module);
237-
if (r == NULL) {
238-
return -1;
239-
}
240-
rc = _PyUnicodeWriter_WriteStr(writer, r);
241-
Py_DECREF(r);
242242
return rc;
243243
}
244244

@@ -248,20 +248,26 @@ union_repr(PyObject *self)
248248
unionobject *alias = (unionobject *)self;
249249
Py_ssize_t len = PyTuple_GET_SIZE(alias->args);
250250

251-
_PyUnicodeWriter writer;
252-
_PyUnicodeWriter_Init(&writer);
253-
for (Py_ssize_t i = 0; i < len; i++) {
254-
if (i > 0 && _PyUnicodeWriter_WriteASCIIString(&writer, " | ", 3) < 0) {
251+
// Shortest type name "int" (3 chars) + " | " (3 chars) separator
252+
Py_ssize_t estimate = (len <= PY_SSIZE_T_MAX / 6) ? len * 6 : len;
253+
PyUnicodeWriter *writer = PyUnicodeWriter_Create(estimate);
254+
if (writer == NULL) {
255+
return NULL;
256+
}
257+
258+
for (Py_ssize_t i = 0; i < len; i++) {
259+
if (i > 0 && PyUnicodeWriter_WriteUTF8(writer, " | ", 3) < 0) {
255260
goto error;
256261
}
257262
PyObject *p = PyTuple_GET_ITEM(alias->args, i);
258-
if (union_repr_item(&writer, p) < 0) {
263+
if (union_repr_item(writer, p) < 0) {
259264
goto error;
260265
}
261266
}
262-
return _PyUnicodeWriter_Finish(&writer);
267+
return PyUnicodeWriter_Finish(writer);
268+
263269
error:
264-
_PyUnicodeWriter_Dealloc(&writer);
270+
PyUnicodeWriter_Discard(writer);
265271
return NULL;
266272
}
267273

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy