Time#strftime: avoid repeated coderange scanning

Followup: a3f589640f

Restarting scanning has a fixed cost. Since we build a string
from many small parts, that causes the scan to restart many times.

It's much faster to ignore the coderange, if it's needed later it
will be faster to scan it in one go.

```
compare-ruby: ruby 3.4.0dev (2024-09-04T11:54:06Z opt-strftime-growth 149480f0ff) +YJIT [arm64-darwin23]
built-ruby: ruby 3.4.0dev (2024-09-04T11:55:26Z opt-strftime-coder.. 29a5153cba) +YJIT [arm64-darwin23]
warming up...

|                            |compare-ruby|built-ruby|
|:---------------------------|-----------:|---------:|
|time.strftime("%FT%T")      |      1.870M|    2.225M|
|                            |           -|     1.19x|
|time.strftime("%FT%T.%3N")  |      1.731M|    2.068M|
|                            |           -|     1.19x|
|time.strftime("%FT%T.%6N")  |      1.744M|    2.073M|
|                            |           -|     1.19x|
```

Cumulative with a3f589640fd443deea230c27efd6bdfc92f5817f:

```
compare-ruby: ruby 3.4.0dev (2024-09-04T11:55:26Z opt-strftime-coder.. 29a5153cba) +YJIT [arm64-darwin23]
built-ruby: ruby 3.4.0dev (2024-09-04T12:57:30Z opt-strftime-coder.. 2b938d667a) +YJIT [arm64-darwin23]
warming up...

|                            |compare-ruby|built-ruby|
|:---------------------------|-----------:|---------:|
|time.strftime("%FT%T")      |      1.784M|    2.277M|
|                            |           -|     1.28x|
|time.strftime("%FT%T.%3N")  |      1.504M|    2.056M|
|                            |           -|     1.37x|
|time.strftime("%FT%T.%6N")  |      1.489M|    2.094M|
|                            |           -|     1.41x|
```
This commit is contained in:
Jean Boussier 2024-09-04 12:52:18 +02:00
Родитель 2e5a7d768b
Коммит 294dad22d7
2 изменённых файлов: 5 добавлений и 1 удалений

Просмотреть файл

@ -1165,7 +1165,9 @@ ruby_vsprintf0(VALUE result, char *p, const char *fmt, va_list ap)
RBASIC_SET_CLASS_RAW(result, klass);
p = RSTRING_PTR(result);
long blen = (char *)f._p - p;
if (scanned < blen) {
coderange = ENC_CODERANGE(result);
if (coderange != ENC_CODERANGE_UNKNOWN && scanned < blen) {
rb_str_coderange_scan_restartable(p + scanned, p + blen, rb_enc_get(result), &coderange);
ENC_CODERANGE_SET(result, coderange);
}

Просмотреть файл

@ -932,6 +932,7 @@ rb_strftime(const char *format, size_t format_len, rb_encoding *enc,
VALUE time, const struct vtm *vtm, VALUE timev, int gmt)
{
VALUE result = rb_enc_str_new(0, 0, enc);
ENC_CODERANGE_CLEAR(result);
return rb_strftime_with_timespec(result, format, format_len, enc,
time, vtm, timev, NULL, gmt,
strftime_size_limit(format_len));
@ -942,6 +943,7 @@ rb_strftime_timespec(const char *format, size_t format_len, rb_encoding *enc,
VALUE time, const struct vtm *vtm, struct timespec *ts, int gmt)
{
VALUE result = rb_enc_str_new(0, 0, enc);
ENC_CODERANGE_CLEAR(result);
return rb_strftime_with_timespec(result, format, format_len, enc,
time, vtm, Qnil, ts, gmt,
strftime_size_limit(format_len));