Improve performance of String#codepoints with ASCII hot path in multi-byte strings. (#16991)

This commit is contained in:
FletcherDares authored and GitHub committed 2026-05-23 08:16:43 +09:00
1 parent 8e5cf5ceca
commit a6c4e98cbd
2 files changed
+17 -1
Notes: git 2026-05-22 23:17:12 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
prelude: |
mixed_ascii64 = ("a" * 63 + "\u{100}") * 2048
mixed_ascii256 = ("a" * 255 + "\u{100}") * 512
utf8_2byte = "\u{100}" * 65536
benchmark:
codepoints_mixed_ascii64: mixed_ascii64.codepoints
codepoints_mixed_ascii256: mixed_ascii256.codepoints
codepoints_utf8_2byte: utf8_2byte.codepoints
+8 -1
View File
@@ -9772,6 +9772,7 @@ rb_str_enumerate_codepoints(VALUE str, VALUE ary)
unsigned int c;
const char *ptr, *end;
rb_encoding *enc;
int enc_asciicompat;
if (single_byte_optimizable(str))
return rb_str_enumerate_bytes(str, ary);
@@ -9780,9 +9781,15 @@ rb_str_enumerate_codepoints(VALUE str, VALUE ary)
ptr = RSTRING_PTR(str);
end = RSTRING_END(str);
enc = STR_ENC_GET(str);
enc_asciicompat = rb_enc_asciicompat(enc);
while (ptr < end) {
c = rb_enc_codepoint_len(ptr, end, &n, enc);
/* Fast path: ASCII byte in an ASCII-compatible encoding is its own codepoint;
* skip rb_enc_codepoint_len and return the byte directly.
*/
n = 1;
c = (enc_asciicompat && ISASCII(*ptr)) ?
(unsigned char)*ptr : rb_enc_codepoint_len(ptr, end, &n, enc);
ENUM_ELEM(ary, UINT2NUM(c));
ptr += n;
}