Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't call Warning.warn unless the category is enabled #10960

Merged
merged 1 commit into from
Jun 11, 2024

Conversation

tenderlove
Copy link
Member

The warning category should be enabled if we want to call Warning.warn.

This commit speeds up the following benchmark:

eval "def test; " +
  1000.times.map { "'  '.chomp!" }.join(";") + "; end"

def run_benchmark count
  i = 0
  while i < count
    start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    yield
    ms = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
    puts "itr ##{i}: #{(ms * 1000).to_i}ms"
    i += 1
  end
end

run_benchmark(25) do
  250.times do
    test
  end
end

On master this runs at about 92ms per iteration. With this patch, it is 7ms per iteration.

Copy link
Contributor

@jeremyevans jeremyevans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a safe optimization if Warning.warn is not overridden. However, if Warning.warn is overridden, this silences a warning that Warning.warn would previously get called with. Maybe that isn't a problem, but I think this change would need to be discussed at a developer meeting, unless it was limited to cases where Warning.warn was not overridden.

@tenderlove
Copy link
Member Author

This should be a safe optimization if Warning.warn is not overridden. However, if Warning.warn is overridden, this silences a warning that Warning.warn would previously get called with. Maybe that isn't a problem, but I think this change would need to be discussed at a developer meeting, unless it was limited to cases where Warning.warn was not overridden.

Ya, I think we could do monkey patch detection and handle that. I'll make a redmine ticket for it. As it stands, this is unfortunately causing a performance regression in some of the benchmarks we're watching (see the etanni benchmark here)

@nobu
Copy link
Member

nobu commented Jun 11, 2024

Also rb_category_warning?

@byroot
Copy link
Member

byroot commented Jun 11, 2024

To me this is a bug fix, if I set Warning[:performance] = false, I don't want my Warning.warn patch called for performance warnings.

@tenderlove
Copy link
Member Author

Also rb_category_warning?

Yes, thanks @nobu

@tenderlove tenderlove marked this pull request as ready for review June 11, 2024 16:03
@matzbot matzbot requested a review from a team June 11, 2024 16:03
@tenderlove
Copy link
Member Author

tenderlove commented Jun 11, 2024

According to @byroot, this restores the behavior from Ruby 2.7.8 (see this ticket). In other words, I think this is a bugfix.

@tenderlove
Copy link
Member Author

@jeremyevans this seems like a bugfix to me, but I'd like to know your opinion 😄

Copy link
Contributor

@jeremyevans jeremyevans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the discussion at https://bugs.ruby-lang.org/issues/20573, I agree this is a bug fix.

The warning category should be enabled if we want to call
`Warning.warn`.

This commit speeds up the following benchmark:

```ruby
eval "def test; " +
  1000.times.map { "'  '.chomp!" }.join(";") + "; end"

def run_benchmark count
  i = 0
  while i < count
    start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    yield
    ms = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
    puts "itr ##{i}: #{(ms * 1000).to_i}ms"
    i += 1
  end
end

run_benchmark(25) do
  250.times do
    test
  end
end
```

On `master` this runs at about 92ms per iteration. With this patch, it
is 7ms per iteration.

[Bug #20573]
@tenderlove tenderlove enabled auto-merge (rebase) June 11, 2024 21:11
@tenderlove tenderlove merged commit 1271ff7 into ruby:master Jun 11, 2024
105 of 106 checks passed
@tenderlove tenderlove deleted the warning-warn branch June 11, 2024 21:55
casperisfine pushed a commit to Shopify/ruby that referenced this pull request Jun 12, 2024
[Bug #20573]

Followup: ruby#10960

I believe `Kernel#warn` should behave in the same way than internal
`rb_warning_* APIs
casperisfine pushed a commit to Shopify/ruby that referenced this pull request Jun 12, 2024
[Bug #20573]

Followup: ruby#10960

I believe `Kernel#warn` should behave in the same way than internal
`rb_warning_* APIs
casperisfine pushed a commit to Shopify/ruby that referenced this pull request Jun 12, 2024
[Bug #20573]

Followup: ruby#10960

I believe `Kernel#warn` should behave in the same way than internal
`rb_warning_* APIs
casperisfine pushed a commit to Shopify/ruby that referenced this pull request Jun 12, 2024
[Bug #20573]

Followup: ruby#10960

I believe `Kernel#warn` should behave in the same way than internal
`rb_warning_* APIs
casperisfine pushed a commit to Shopify/ruby that referenced this pull request Jun 12, 2024
[Bug #20573]

Followup: ruby#10960

I believe `Kernel#warn` should behave in the same way than internal
`rb_warning_* APIs
byroot added a commit that referenced this pull request Jun 12, 2024
[Bug #20573]

Followup: #10960

I believe `Kernel#warn` should behave in the same way than internal
`rb_warning_* APIs
andrykonchin pushed a commit to ruby/spec that referenced this pull request Jul 1, 2024
[Bug #20573]

Followup: ruby/ruby#10960

I believe `Kernel#warn` should behave in the same way than internal
`rb_warning_* APIs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants