Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Optimized ``PyUnicode_GetString`` for short ASCII strings.
28 changes: 22 additions & 6 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2163,12 +2163,27 @@ PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size)
PyObject *
PyUnicode_FromString(const char *u)
{
size_t size = strlen(u);
if (size > PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError, "input too long");
return NULL;
/* Most calls of PyUnicode_FromString is for short ASCII string.
* So we optimize this function for them.
*/
size_t len = 0;
int is_ascii = 1;

while (u[len] != '\0') {
if (u[len] > 127) {
is_ascii = 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you reuse fast _Py_bytes_isascii() somehow here? It works on unsigned long words (64 bits) rather than working on bytes (8 bits): it should be 8x faster.

}
len++;
if (len > PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError, "input too long");
return NULL;
}
}
return PyUnicode_DecodeUTF8Stateful(u, (Py_ssize_t)size, NULL, NULL);

if (is_ascii) {
return _PyUnicode_FromASCII(u, (Py_ssize_t)len);
}
return PyUnicode_DecodeUTF8Stateful(u, (Py_ssize_t)len, NULL, NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not modifying PyUnicode_DecodeUTF8Stateful() to detect if the input string is ASCII, or your heuristic is faster? Is it because it make non-ASCII string decoding slower?

}

PyObject *
Expand Down Expand Up @@ -15303,8 +15318,9 @@ PyObject *
PyUnicode_InternFromString(const char *cp)
{
PyObject *s = PyUnicode_FromString(cp);
if (s == NULL)
if (s == NULL) {
return NULL;
}
PyUnicode_InternInPlace(&s);
return s;
}
Expand Down