From: "kyanagi (Kouhei Yanagita) via ruby-core" Date: 2023-09-28T05:20:18+00:00 Subject: [ruby-core:114908] [Ruby master Feature#18515] Add Range#reverse_each implementation for performance Issue #18515 has been updated by kyanagi (Kouhei Yanagita). Let's set aside `#pred` for now to avoid going off track. I have created a new pull request with a simpler implementation and closed the old one. New PR: https://github.com/ruby/ruby/pull/8525 As benchmark results show, huge memory savings are achieved, especially for large `Range`. Execution speed is also increased. ``` prelude: | rf_1 = 0..1 rf_1k = 0..1000 rf_1m = 0..1000000 big = 2**1000 rb_1 = big..big+1 rb_1k = big..big+1000 rb_1m = big..big+1000000 benchmark: "Fixnum 1": rf_1.reverse_each { _1 } "Fixnum 1K": rf_1k.reverse_each { _1 } "Fixnum 1M": rf_1m.reverse_each { _1 } "Bignum 1": rb_1.reverse_each { _1 } "Bignum 1K": rb_1k.reverse_each { _1 } "Bignum 1M": rb_1m.reverse_each { _1 } ``` ### Max resident set size (bytes) | |master |PR |ratio| |:----------|--------:|-------:|----:| |Fixnum 1 | 13.910M| 14.877M|1.069| |Fixnum 1K | 14.778M| 14.762M|0.998| |Fixnum 1M | 28.770M| 14.025M|0.487| |Bignum 1 | 14.729M| 14.189M|0.963| |Bignum 1K | 14.074M| 13.582M|0.965| |Bignum 1M | 224.723M| 15.254M|0.067| ### Iteration per second (i/s) | |master |PR |ratio| |:----------|------:|-------:|----:| |Fixnum 1 | 6.653M| 14.511M|2.181| |Fixnum 1K |27.866k| 45.527k|1.633| |Fixnum 1M | 28.659| 45.667|1.593| |Bignum 1 | 3.534M| 4.635M|1.311| |Bignum 1K | 6.790k| 7.693k|1.132| |Bignum 1M | 5.720| 7.532|1.316| ---------------------------------------- Feature #18515: Add Range#reverse_each implementation for performance https://bugs.ruby-lang.org/issues/18515#change-104776 * Author: kyanagi (Kouhei Yanagita) * Status: Open * Priority: Normal ---------------------------------------- PR is https://github.com/ruby/ruby/pull/5489 Current `Range#reverse_each` uses `Enumerable#reverse_each` which is implemented with `#to_a`. So we are virtually not able to use `reverse_each` for a very large or beginless range, even if few elements are iterated on actually. ``` (1..2**100).reverse_each { |x| p x; break if x.odd? } (..5).reverse_each { |x| p x; break if x == 0 } (1..2**32).reverse_each.lazy.select { |x| Prime.prime?(x) }.take(3).to_a ``` This patch, implements `Range#reverse_each` for Integer elements, enables these examples. I think `#reverse_each` for an endless range should raise an exception. This is a different issue, so I'll create another ticket later. -> posted: https://bugs.ruby-lang.org/issues/18551 -- 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-core.ml.ruby-lang.org/