Skip to content

Commit c0cd6da

Browse files
vstinnermrahtz
authored andcommitted
pythongh-119182: Use public PyUnicodeWriter API in ga_repr() (python#120799)
The public PyUnicodeWriter API enables overallocation by default and so is more efficient. Benchmark: python -m pyperf timeit \ -s 't = list[int, float, complex, str, bytes, bytearray, ' \ 'memoryview, list, dict]' \ 'str(t)' Result: 1.49 us +- 0.03 us -> 1.10 us +- 0.02 us: 1.35x faster
1 parent f8061a7 commit c0cd6da

File tree

1 file changed

+35
-33
lines changed

1 file changed

+35
-33
lines changed

Objects/genericaliasobject.c

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,15 @@ ga_traverse(PyObject *self, visitproc visit, void *arg)
5151
}
5252

5353
static int
54-
ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
54+
ga_repr_item(PyUnicodeWriter *writer, PyObject *p)
5555
{
5656
PyObject *qualname = NULL;
5757
PyObject *module = NULL;
58-
PyObject *r = NULL;
5958
int rc;
6059

6160
if (p == Py_Ellipsis) {
6261
// The Ellipsis object
63-
r = PyUnicode_FromString("...");
62+
rc = PyUnicodeWriter_WriteUTF8(writer, "...", 3);
6463
goto done;
6564
}
6665

@@ -71,17 +70,17 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
7170
goto use_repr;
7271
}
7372
if (rc < 0) {
74-
goto done;
73+
goto error;
7574
}
7675

7776
if (PyObject_GetOptionalAttr(p, &_Py_ID(__qualname__), &qualname) < 0) {
78-
goto done;
77+
goto error;
7978
}
8079
if (qualname == NULL) {
8180
goto use_repr;
8281
}
8382
if (PyObject_GetOptionalAttr(p, &_Py_ID(__module__), &module) < 0) {
84-
goto done;
83+
goto error;
8584
}
8685
if (module == NULL || module == Py_None) {
8786
goto use_repr;
@@ -92,45 +91,42 @@ ga_repr_item(_PyUnicodeWriter *writer, PyObject *p)
9291
_PyUnicode_EqualToASCIIString(module, "builtins"))
9392
{
9493
// builtins don't need a module name
95-
r = PyObject_Str(qualname);
94+
rc = PyUnicodeWriter_WriteStr(writer, qualname);
9695
goto done;
9796
}
9897
else {
99-
r = PyUnicode_FromFormat("%S.%S", module, qualname);
98+
rc = PyUnicodeWriter_Format(writer, "%S.%S", module, qualname);
10099
goto done;
101100
}
102101

102+
error:
103+
rc = -1;
104+
goto done;
105+
103106
use_repr:
104-
r = PyObject_Repr(p);
107+
rc = PyUnicodeWriter_WriteRepr(writer, p);
108+
goto done;
105109

106110
done:
107111
Py_XDECREF(qualname);
108112
Py_XDECREF(module);
109-
if (r == NULL) {
110-
// error if any of the above PyObject_Repr/PyUnicode_From* fail
111-
rc = -1;
112-
}
113-
else {
114-
rc = _PyUnicodeWriter_WriteStr(writer, r);
115-
Py_DECREF(r);
116-
}
117113
return rc;
118114
}
119115

120116
static int
121-
ga_repr_items_list(_PyUnicodeWriter *writer, PyObject *p)
117+
ga_repr_items_list(PyUnicodeWriter *writer, PyObject *p)
122118
{
123119
assert(PyList_CheckExact(p));
124120

125121
Py_ssize_t len = PyList_GET_SIZE(p);
126122

127-
if (_PyUnicodeWriter_WriteASCIIString(writer, "[", 1) < 0) {
123+
if (PyUnicodeWriter_WriteChar(writer, '[') < 0) {
128124
return -1;
129125
}
130126

131127
for (Py_ssize_t i = 0; i < len; i++) {
132128
if (i > 0) {
133-
if (_PyUnicodeWriter_WriteASCIIString(writer, ", ", 2) < 0) {
129+
if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) {
134130
return -1;
135131
}
136132
}
@@ -140,7 +136,7 @@ ga_repr_items_list(_PyUnicodeWriter *writer, PyObject *p)
140136
}
141137
}
142138

143-
if (_PyUnicodeWriter_WriteASCIIString(writer, "]", 1) < 0) {
139+
if (PyUnicodeWriter_WriteChar(writer, ']') < 0) {
144140
return -1;
145141
}
146142

@@ -153,49 +149,55 @@ ga_repr(PyObject *self)
153149
gaobject *alias = (gaobject *)self;
154150
Py_ssize_t len = PyTuple_GET_SIZE(alias->args);
155151

156-
_PyUnicodeWriter writer;
157-
_PyUnicodeWriter_Init(&writer);
152+
// Estimation based on the shortest format: "int[int, int, int]"
153+
Py_ssize_t estimate = (len <= PY_SSIZE_T_MAX / 5) ? len * 5 : len;
154+
estimate = 3 + 1 + estimate + 1;
155+
PyUnicodeWriter *writer = PyUnicodeWriter_Create(estimate);
156+
if (writer == NULL) {
157+
return NULL;
158+
}
158159

159160
if (alias->starred) {
160-
if (_PyUnicodeWriter_WriteASCIIString(&writer, "*", 1) < 0) {
161+
if (PyUnicodeWriter_WriteChar(writer, '*') < 0) {
161162
goto error;
162163
}
163164
}
164-
if (ga_repr_item(&writer, alias->origin) < 0) {
165+
if (ga_repr_item(writer, alias->origin) < 0) {
165166
goto error;
166167
}
167-
if (_PyUnicodeWriter_WriteASCIIString(&writer, "[", 1) < 0) {
168+
if (PyUnicodeWriter_WriteChar(writer, '[') < 0) {
168169
goto error;
169170
}
170171
for (Py_ssize_t i = 0; i < len; i++) {
171172
if (i > 0) {
172-
if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
173+
if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) {
173174
goto error;
174175
}
175176
}
176177
PyObject *p = PyTuple_GET_ITEM(alias->args, i);
177178
if (PyList_CheckExact(p)) {
178179
// Looks like we are working with ParamSpec's list of type args:
179-
if (ga_repr_items_list(&writer, p) < 0) {
180+
if (ga_repr_items_list(writer, p) < 0) {
180181
goto error;
181182
}
182183
}
183-
else if (ga_repr_item(&writer, p) < 0) {
184+
else if (ga_repr_item(writer, p) < 0) {
184185
goto error;
185186
}
186187
}
187188
if (len == 0) {
188189
// for something like tuple[()] we should print a "()"
189-
if (_PyUnicodeWriter_WriteASCIIString(&writer, "()", 2) < 0) {
190+
if (PyUnicodeWriter_WriteUTF8(writer, "()", 2) < 0) {
190191
goto error;
191192
}
192193
}
193-
if (_PyUnicodeWriter_WriteASCIIString(&writer, "]", 1) < 0) {
194+
if (PyUnicodeWriter_WriteChar(writer, ']') < 0) {
194195
goto error;
195196
}
196-
return _PyUnicodeWriter_Finish(&writer);
197+
return PyUnicodeWriter_Finish(writer);
198+
197199
error:
198-
_PyUnicodeWriter_Dealloc(&writer);
200+
PyUnicodeWriter_Discard(writer);
199201
return NULL;
200202
}
201203

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