Skip to content

Commit d43b1b5

Browse files
committed
gh-158451: Optimize PyUnicode_Join()
Move tests on the separator outside the loop. Add a loop version for empty separator.
1 parent 9d22a53 commit d43b1b5

1 file changed

Lines changed: 57 additions & 33 deletions

File tree

‎Objects/unicodeobject.c‎

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,8 +1835,7 @@ PyUnicode_Resize(PyObject **p_unicode, Py_ssize_t length)
18351835
static PyObject*
18361836
get_latin1_char(Py_UCS1 ch)
18371837
{
1838-
PyObject *o = LATIN1(ch);
1839-
return o;
1838+
return LATIN1(ch);
18401839
}
18411840

18421841
static PyObject*
@@ -10489,9 +10488,7 @@ _PyUnicode_JoinArray(PyObject *separator, PyObject *const *items, Py_ssize_t seq
1048910488
/* Set up sep and seplen */
1049010489
if (separator == NULL) {
1049110490
/* fall back to a blank space separator */
10492-
sep = PyUnicode_FromOrdinal(' ');
10493-
if (!sep)
10494-
goto onError;
10491+
sep = get_latin1_char(' ');
1049510492
seplen = 1;
1049610493
maxchar = 32;
1049710494
}
@@ -10562,51 +10559,78 @@ _PyUnicode_JoinArray(PyObject *separator, PyObject *const *items, Py_ssize_t seq
1056210559
use_memcpy = 0;
1056310560
#else
1056410561
if (use_memcpy) {
10565-
res_data = PyUnicode_1BYTE_DATA(res);
10562+
res_data = PyUnicode_DATA(res);
1056610563
kind = PyUnicode_KIND(res);
1056710564
if (seplen != 0)
10568-
sep_data = PyUnicode_1BYTE_DATA(sep);
10565+
sep_data = PyUnicode_DATA(sep);
1056910566
}
1057010567
#endif
1057110568
if (use_memcpy) {
10572-
for (i = 0; i < seqlen; ++i) {
10573-
Py_ssize_t itemlen;
10574-
item = items[i];
10575-
10576-
/* Copy item, and maybe the separator. */
10577-
if (i && seplen != 0) {
10578-
memcpy(res_data,
10579-
sep_data,
10580-
kind * seplen);
10581-
res_data += kind * seplen;
10582-
}
10583-
10584-
itemlen = PyUnicode_GET_LENGTH(item);
10569+
if (seplen != 0) {
10570+
item = items[0];
10571+
Py_ssize_t itemlen = PyUnicode_GET_LENGTH(item);
1058510572
if (itemlen != 0) {
10586-
memcpy(res_data,
10587-
PyUnicode_DATA(item),
10588-
kind * itemlen);
10573+
memcpy(res_data, PyUnicode_DATA(item), kind * itemlen);
1058910574
res_data += kind * itemlen;
1059010575
}
10576+
10577+
for (i = 1; i < seqlen; ++i) {
10578+
/* Copy item, and maybe the separator. */
10579+
memcpy(res_data, sep_data, kind * seplen);
10580+
res_data += kind * seplen;
10581+
10582+
item = items[i];
10583+
itemlen = PyUnicode_GET_LENGTH(item);
10584+
if (itemlen != 0) {
10585+
memcpy(res_data, PyUnicode_DATA(item), kind * itemlen);
10586+
res_data += kind * itemlen;
10587+
}
10588+
}
10589+
}
10590+
else {
10591+
for (i = 0; i < seqlen; ++i) {
10592+
item = items[i];
10593+
Py_ssize_t itemlen = PyUnicode_GET_LENGTH(item);
10594+
if (itemlen != 0) {
10595+
memcpy(res_data, PyUnicode_DATA(item), kind * itemlen);
10596+
res_data += kind * itemlen;
10597+
}
10598+
}
1059110599
}
1059210600
assert(res_data == PyUnicode_1BYTE_DATA(res)
1059310601
+ kind * PyUnicode_GET_LENGTH(res));
1059410602
}
1059510603
else {
10596-
for (i = 0, res_offset = 0; i < seqlen; ++i) {
10597-
Py_ssize_t itemlen;
10598-
item = items[i];
10604+
if (seplen != 0) {
10605+
res_offset = 0;
10606+
item = items[0];
10607+
Py_ssize_t itemlen = PyUnicode_GET_LENGTH(item);
10608+
if (itemlen != 0) {
10609+
_PyUnicode_FastCopyCharacters(res, res_offset, item, 0, itemlen);
10610+
res_offset += itemlen;
10611+
}
1059910612

10600-
/* Copy item, and maybe the separator. */
10601-
if (i && seplen != 0) {
10613+
for (i = 1; i < seqlen; ++i) {
10614+
/* Copy item, and maybe the separator. */
1060210615
_PyUnicode_FastCopyCharacters(res, res_offset, sep, 0, seplen);
1060310616
res_offset += seplen;
10604-
}
1060510617

10606-
itemlen = PyUnicode_GET_LENGTH(item);
10607-
if (itemlen != 0) {
10608-
_PyUnicode_FastCopyCharacters(res, res_offset, item, 0, itemlen);
10609-
res_offset += itemlen;
10618+
item = items[i];
10619+
itemlen = PyUnicode_GET_LENGTH(item);
10620+
if (itemlen != 0) {
10621+
_PyUnicode_FastCopyCharacters(res, res_offset, item, 0, itemlen);
10622+
res_offset += itemlen;
10623+
}
10624+
}
10625+
}
10626+
else {
10627+
for (i = 0, res_offset = 0; i < seqlen; ++i) {
10628+
item = items[i];
10629+
Py_ssize_t itemlen = PyUnicode_GET_LENGTH(item);
10630+
if (itemlen != 0) {
10631+
_PyUnicode_FastCopyCharacters(res, res_offset, item, 0, itemlen);
10632+
res_offset += itemlen;
10633+
}
1061010634
}
1061110635
}
1061210636
assert(res_offset == PyUnicode_GET_LENGTH(res));

0 commit comments

Comments
 (0)