Issue #19444 has been reported by alanwu (Alan Wu).
----------------------------------------
Bug #19444: YJIT String#+@ miscompilations
https://bugs.ruby-lang.org/issues/19444
* Author: alanwu (Alan Wu)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: REQUIRED
----------------------------------------
We noticed two issues with YJIT's `String#+@` (String unary plus) implementation.
1. It has issues with GC allocation tracing. We saw it SEGV with the `Stackprof` gem
2. It has a type confusion issue from assuming that the method always return an `::String` instance. It can return subclass instances
The YJIT override does not exist on the 3.1 series.
--
https://bugs.ruby-lang.org/
Issue #18604 has been updated by Hombre2014 (Yuriy Chamkoriyski).
I had the same problem with ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [arm64-darwin21]. It crashed my app. It seems that ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21] as reported by Joe Ruth still has the problem. What is the status of this bug? Has it been fixed? If so, in which version?
Thanks.
----------------------------------------
Bug #18604: [BUG] ERROR(VpDivd): space for remainder too small
https://bugs.ruby-lang.org/issues/18604#change-102182
* Author: mentalizer (Jakob Skjerning)
* Status: Third Party's Issue
* Priority: Normal
* ruby -v: ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [arm64-darwin21]
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
After upgrading to Ruby 3.1 one of our statistical dashboards started crashing with a message saying
[BUG] ERROR(VpDivd): space for remainder too small
### How to reproduce
This can be reproduced in irb (reproduction script is attached containing the below code):
``` ruby
$ irb
3.1.1 :001 > require "bigdecimal"
=> true
3.1.1 :002 > 1.0 / BigDecimal("0.9652409267836026803310997240835632636973e2")
```
### Actual result
```ruby
(irb):2: [BUG] ERROR(VpDivd): space for remainder too small.
ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [arm64-darwin21]
-- Crash Report log information --------------------------------------------
...
```
Full output from running reproduction script has been attached.
### Expected results
The result of division, which is roughly:
```
=> 0.10360107743589181177761764314914637186293143963577706371029263e-1
```
### Affected Rubies
So far I've been able to reproduce this on...
- ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [arm64-darwin21]
- ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-linux]
- ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [arm64-darwin21]
The following seem to work just fine:
- ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [arm64-darwin21]
### Notes
Admittedly, the precision here is way higher that we actually need it to be, and our workaround has been to simply convert the BigDecimal to Float before dividing.
```ruby
1.0 / BigDecimal("0.9652409267836026803310997240835632636973e2").to_f
# => 0.010360107743589182
```
---Files--------------------------------
repro.rb (86 Bytes)
ruby-2022-02-24-161721.ips (96 KB)
crash.log (469 KB)
--
https://bugs.ruby-lang.org/
Issue #19377 has been reported by zverok (Victor Shepelev).
----------------------------------------
Feature #19377: Rename Fiber#storage to Fiber.storage
https://bugs.ruby-lang.org/issues/19377
* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
----------------------------------------
Justification:
* `#storage`, which pretends to be an instance method, is always available only on `Fiber.current`, which is [problematic to document](https://github.com/ruby/ruby/pull/6985#discussion_r1055796069), and needs special handling when `storage` is called for non-current Fiber;
* with class method + docs "storage of the current fiber" it all will be self-evident;
* Most of the time, when we declare methods that are available only in the current {something}, they are class methods. (like storage's itself interface of `Fiber::[]` and `Fiber::[]=`, or `Module.used_modules`, which is modules and refinements of the _current context_, but it is not `self.used_modules`, for example)
* Code like
```ruby
Fiber.current.storage = {foo: 'bar'}
Fiber[:foo]
```
...looks like it is two unrelated things (storage of the _current_ fiber vs some "global" key getter/setter?)
I don't see much discussion of this in #19078. Matz in 19078#note-22, while accepting the interface, describes it as homogenous:
> (1) fiber[key]/fiber[key]=val - accepted.
> (2) fiber.storage => hash - accepted
> (3) fiber.storage=hash - should be experimental
> ...
So I believe it should be either `Fiber.current[]` and `Fiber.current.storage`, or `Fiber[]`, and `Fiber.storage`. The latter is preferable to underline it is only one, related to the current fiber, interface, not "every fiber instance has one (but actually you can use only `current`'s)
--
https://bugs.ruby-lang.org/
Issue #19470 has been reported by giner (Stanislav German-Evtushenko).
----------------------------------------
Bug #19470: Frequent small range-reads from and then writes to a large array are very slow
https://bugs.ruby-lang.org/issues/19470
* Author: giner (Stanislav German-Evtushenko)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-linux]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
Write to a large array gets very slow when done after range-reading more than 3 items. In such case the original array gets marked as shared which triggers CoW on a small change afterwards. This leads to a significant performance impact and high memory utilization in cases when we need to range-read/write from/to the same array many times. While this issue can be avoided by reading <= 3 elements at a time the main problem is that this behaviour is not obvious and hard to catch on on-trivial projects.
```ruby
times = []
arr = [0] * 100000
times.push 0
100000.times do
time_start = Time.now
arr[5] = 100 # takes 0.01662315899999512
times[-1] += Time.now - time_start
end
times.push 0
100000.times do
arr[0..2]
time_start = Time.now
arr[5] = 100 # takes 0.01826406799999659
times[-1] += Time.now - time_start
end
times.push 0
100000.times do
arr[0..3]
time_start = Time.now
arr[5] = 100 # takes 7.757753919000069
times[-1] += Time.now - time_start
end
times.push 0
100000.times do
arr.dup
time_start = Time.now
arr[5] = 100 # takes 7.626929300999957
times[-1] += Time.now - time_start
end
times.push 0
100000.times do
arr.clone
time_start = Time.now
arr[5] = 100 # takes 8.216933763000046
times[-1] += Time.now - time_start
end
p times
```
--
https://bugs.ruby-lang.org/
Issue #19451 has been reported by ioquatix (Samuel Williams).
----------------------------------------
Feature #19451: Extract path and line number from SyntaxError?
https://bugs.ruby-lang.org/issues/19451
* Author: ioquatix (Samuel Williams)
* Status: Open
* Priority: Normal
----------------------------------------
There doesn't seem to be any official way to extract the path and line number from a syntax error.
There are two ways I can see us dong this:
- Provide explicit `path` and `line_number` attributes.
- Prepend them to `backtrace_locations`.
The nice thing about the latter approach is that it will just work with existing tools which understand how to highlight code based on backtrace locations.
Maybe we should do both?
--
https://bugs.ruby-lang.org/
Issue #19438 has been reported by nick.schwaderer (Nicholas Schwaderer).
----------------------------------------
Bug #19438: Ruby 2.7 -> 3.2 Performance Regression
https://bugs.ruby-lang.org/issues/19438
* Author: nick.schwaderer (Nicholas Schwaderer)
* Status: Open
* Priority: Normal
* ruby -v: 3.2.0
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
## Introduction
Recently I had been going through some of the old benchmarks in the [Ruby Great Implementation Shootout](https://programmingzen.com/the-great-ruby-shootout-july-2010/) from around 2010.
As an experiment, one night I ran the benchmarks against Ruby 3.2.0, Ruby 3.2.0 --yjit, TruffleRuby, TruffleRuby +GraalVM, and Ruby 2.6.10.
Most results were as expected. However there was a benchmark that Ruby 2.6.10 was _consistently_ outperforming all new Rubies on.
## Method
After pairing with @eightbitraptor, we discovered that this old benchmark was remarkably similar to an existing benchmark in the `/benchmark`
directory, [so_k_nucleotide.yml](https://github.com/ruby/ruby/blob/master/benchmark/so_…. We decided to go with that benchmark. For brevity I have not included the full 150 lines of the benchmark here.
I tested this benchmark out with 100 runs using `benchmark-driver` against Ruby 2.7,3.0,3.1,3.2. (I had discovered that 2.7 was even faster than 2.6.).
It appears that about half of the regression occured from 2.7 -> 3.0; the other half from 3.0 -> 3.2. One other interesting finding is that each minor version does appear to regress
from the last, even if a little.
## Code
This is my benchmark running code and harnass. [The full code and data can be found here](https://gist.github.com/Schwad/16edf3d7cc5316af4baf23497f3c6a8f)
```ruby
RUNS = 100
results = Hash.new { |h, k| h[k] = [] }
RUNS.times do |i|
puts i
run = `benchmark-driver so_k_nucleotide.yml --chruby '2.7.5;3.0.5;3.1.3;3.2.0' -o simple`
run.scan(/\d\.\d\.\d/).each_with_index do |version, index|
results[version] << run.scan(/\d\.\d\d\d/)[index]
end
end
require 'csv'
columns = results.keys
outdata = CSV.generate do |csv|
csv << columns
RUNS.times do |i|
csv << columns.map { |c| results[c][i] }
end
end
File.write("output.csv", outdata)
```
## Data
Ruby 2.7.5 was consistently ~18-20% faster than Ruby 3.2.0 in this Benchmark
![Screenshot 2023-02-15 at 13 16 10](https://user-images.githubusercontent.com/7865030/219038430-4a124cc6-0d…
## Next Steps
I am happy to help investigate or learn more about this regression if anyone has any ideas.
--
https://bugs.ruby-lang.org/
Issue #18951 has been updated by byroot (Jean Boussier).
Status changed from Open to Rejected
Marking this as rejected.
Will be in Active Support 7.1
----------------------------------------
Feature #18951: Object#with to set and restore attributes around a block
https://bugs.ruby-lang.org/issues/18951#change-102156
* Author: byroot (Jean Boussier)
* Status: Rejected
* Priority: Normal
----------------------------------------
### Use case
A very common pattern in Ruby, especially in testing is to save the value of an attribute, set a new value, and then restore the old value in an `ensure` clause.
e.g. in unit tests
```ruby
def test_something_when_enabled
enabled_was, SomeLibrary.enabled = SomeLibrary.enabled, true
# test things
ensure
SomeLibrary.enabled = enabled_was
end
```
Or sometime in actual APIs:
```ruby
def with_something_enabled
enabled_was = @enabled
@enabled = true
yield
ensure
@enabled = enabled_was
end
```
There is no inherent problem with this pattern, but it can be easy to make a mistake, for instance the unit test example:
```ruby
def test_something_when_enabled
some_call_that_may_raise
enabled_was, SomeLibrary.enabled = SomeLibrary.enabled, true
# test things
ensure
SomeLibrary.enabled = enabled_was
end
```
In the above if `some_call_that_may_raise` actually raises, `SomeLibrary.enabled` is set back to `nil` rather than its original value. I've seen this mistake quite frequently.
### Proposal
I think it would be very useful to have a method on Object to implement this pattern in a correct and easy to use way. The naive Ruby implementation would be:
```ruby
class Object
def with(**attributes)
old_values = {}
attributes.each_key do |key|
old_values[key] = public_send(key)
end
begin
attributes.each do |key, value|
public_send("#{key}=", value)
end
yield
ensure
old_values.each do |key, old_value|
public_send("#{key}=", old_value)
end
end
end
end
```
NB: `public_send` is used because I don't think such method should be usable if the accessors are private.
With usage:
```ruby
def test_something_when_enabled
SomeLibrary.with(enabled: true) do
# test things
end
end
```
```ruby
GC.with(measure_total_time: true, auto_compact: false) do
# do something
end
```
### Alternate names and signatures
If `#with` isn't good, I can also think of:
- `Object#set`
- `Object#apply`
But the `with_` prefix is by far the most used one when implementing methods that follow this pattern.
Also if accepting a Hash is dimmed too much, alternative signatures could be:
- `Object#set(attr_name, value)`
- `Object#set(attr1, value1, [attr2, value2], ...)`
# Some real world code example that could be simplified with method
- `redis-client` `with_timeout` https://github.com/redis-rb/redis-client/blob/23a5c1e2ff688518904f206df8d4a…
- Lots of tests in Rails's codebase:
- Changing `Thread.report_on_exception`: https://github.com/rails/rails/blob/2d2fdc941e7497ca77f99ce5ad404b6e58f043e…
- Changing a class attribute: https://github.com/rails/rails/blob/2d2fdc941e7497ca77f99ce5ad404b6e58f043e…
--
https://bugs.ruby-lang.org/