[#114774] [Ruby master Feature#19884] Make Safe Navigation Operator work on classes — "p8 (Petrik de Heus) via ruby-core" <ruby-core@...>
Issue #19884 has been reported by p8 (Petrik de Heus).
13 messages
2023/09/15
[ruby-core:114779] [Ruby master Bug#19875] Ruby 3.0 -> 3.1 Performance regression in String#count
From:
"Freaky (Thomas Hurst) via ruby-core" <ruby-core@...>
Date:
2023-09-15 12:32:18 UTC
List:
ruby-core #114779
Issue #19875 has been updated by Freaky (Thomas Hurst).
nobu (Nobuyoshi Nakada) wrote in #note-7:
> These are all generated by the same compiler?
Yes - FreeBSD clang version 14.0.5. I also try 15.0.7 to no effect.
gcc 12.2.0 performs much better, though it too has a slightly more modest p=
erformance regression from 4001:
```
'./ruby.gcc12.revert test.rb' ran
1.28 =B1 0.01 times faster than './ruby.clang.revert test.rb'
1.61 =B1 0.01 times faster than './ruby.gcc12.master test.rb'
4.38 =B1 0.04 times faster than './ruby.clang.master test.rb'
```
The obvious solution works for both:
```
diff --git string.c string.c
index deeed4a12a..70644b2338 100644
--- string.c
+++ string.c
@@ -8455,6 +8455,13 @@ rb_str_count(int argc, VALUE *argv, VALUE str)
s =3D RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) =3D=3D 0) return INT2FIX(0);
send =3D RSTRING_END(str);
+ if (RSTRING_LEN(str) < INT_MAX) {
+ i =3D 0;
+ while (s < send) {
+ if (*(unsigned char*)s++ =3D=3D c) i++;
+ }
+ return INT2NUM(i);
+ }
while (s < send) {
if (*(unsigned char*)s++ =3D=3D c) n++;
}
```
```
'./ruby.gcc12.fix test.rb' ran
1.04 =B1 0.01 times faster than './ruby.gcc12.revert test.rb'
1.32 =B1 0.01 times faster than './ruby.clang.fix test.rb'
1.33 =B1 0.02 times faster than './ruby.revert test.rb'
1.68 =B1 0.01 times faster than './ruby.gcc12.master test.rb'
4.57 =B1 0.03 times faster than './ruby.master test.rb'
```
Oh. And you know what this reminds me of? That [one time](https://github.=
com/Freaky/fast-bytecount) I ported Rust's bytecount crate to C.
```
'./ruby.bytecount test.rb' ran
3.73 =B1 0.08 times faster than './ruby.gcc12.fix test.rb'
3.87 =B1 0.08 times faster than './ruby.gcc12.revert test.rb'
4.94 =B1 0.10 times faster than './ruby.clang.fix test.rb'
4.96 =B1 0.11 times faster than './ruby.revert test.rb'
6.27 =B1 0.13 times faster than './ruby.gcc12.master test.rb'
17.05 =B1 0.36 times faster than './ruby.master test.rb'
```
Who needs a compiler to vectorise for you when you can just ... copy what s=
omeone smarter than you did.
----------------------------------------
Bug #19875: Ruby 3.0 -> 3.1 Performance regression in String#count
https://bugs.ruby-lang.org/issues/19875#change-104621
* Author: iz (Illia Zub)
* Status: Feedback
* Priority: Normal
* ruby -v: 3.2.2
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
`String#count` became slower since Ruby 3.1. Originally found by `@Freaky`:=
https://github.com/ruby/ruby/pull/4001#issuecomment-1714779781
Compared using the [`benchmark-driver` gem](https://github.com/benchmark-dr=
iver/benchmark-driver).
```
$ benchmark-driver tmp/string_count_benchmark_driver.yml --rbenv '3.1.1;3.1=
.4;2.7.2;3.2.2;3.0.6' =20
Calculating -------------------------------------
3.1.1 3.1.4 2.7.2 3.2.2 3=
.0.6
count 465.804 463.741 865.783 462.711 857=
.395 i/s - 10.000k times in 21.468251s 21.563768s 11.550239s 21.611783s=
11.663235s
Comparison:
count
2.7.2: 865.8 i/s=20
3.0.6: 857.4 i/s - 1.01x slower
3.1.1: 465.8 i/s - 1.86x slower
3.1.4: 463.7 i/s - 1.87x slower
3.2.2: 462.7 i/s - 1.87x slower
```
Benchmark:
```yml
$ cat ./tmp/string_count_benchmark_driver.yml=20
loop_count: 10_000
prelude: |
html =3D "\nruby\n" * 1024 * 1024
benchmark:
count: html.count($/)
```
---
*Initially, I noticed the difference between `str.count($/)` and `str.lines=
.size` when working on the performance improvement: https://serpapi.com/blo=
g/lines-count-failed-deployments/*
---Files--------------------------------
rb_str_len.fast (31.9 KB)
rb_str_len.slow (34 KB)
revert-4001.patch (1.71 KB)
rb_str_count.S (11.8 KB)
--=20
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-c=
ore.ml.ruby-lang.org/