diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-11-01-16-02-42.gh-issue-161145.5vLdrm.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-11-01-16-02-42.gh-issue-161145.5vLdrm.rst new file mode 100644 index 00000000000000..5d809624e25f42 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-11-01-16-02-42.gh-issue-161145.5vLdrm.rst @@ -0,0 +1,2 @@ +Speed up UTF-8 decoding of long ASCII runs, such as in :meth:`bytes.decode`, +by up to 1.5x. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index ded13cc37f69f1..4482b6e8d1467f 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5076,6 +5076,17 @@ find_first_nonascii(const unsigned char *start, const unsigned char *end) } #endif + // Long ASCII runs: test eight words per branch. + while (end - p >= 8 * SIZEOF_SIZE_T) { + const size_t *w = (const size_t *)p; + if ((w[0] | w[1] | w[2] | w[3] | + w[4] | w[5] | w[6] | w[7]) & ASCII_CHAR_MASK) + { + break; + } + p += 8 * SIZEOF_SIZE_T; + } + const unsigned char *e = end - SIZEOF_SIZE_T; while (p <= e) { size_t u = (*(const size_t *)p) & ASCII_CHAR_MASK;