Bug #20573
closedWarning.warn shouldn't be called for disabled warnings
Description
Currently Warning.warn
will be called for all warnings, even if that particular category is disabled.
For example
module Warning
def warn(message, category:)
p message => category
end
end
def get_var
$=
end
p Warning[:deprecated]
get_var
I think that internally we should not call Warning.warn
unless the category is enabled.
I've sent a PR here: https://github.com/ruby/ruby/pull/10960
Updated by tenderlovemaking (Aaron Patterson) 7 months ago
Oops, I send this before pasting the output of the script:
$ ./miniruby test.rb
false
{"test.rb:8: warning: variable $= is no longer effective\n"=>:deprecated}
You can see that "deprecated" warnings are not enabled, but Warning.warn
is still called.
Updated by byroot (Jean Boussier) 7 months ago
Agreed, Warning.warn
patches shouldn't be called for disabled categories.
I was actually 100% convinced this was the behavior, and this fix is consistent with Warning.warn
not being invoked for verbose warnings when $VERBOSE = false
.
Updated by byroot (Jean Boussier) 7 months ago
- Related to Feature #17122: Add category to Warning#warn added
Updated by byroot (Jean Boussier) 7 months ago
- Related to Feature #16345: Don't emit deprecation warnings by default. added
Updated by byroot (Jean Boussier) 7 months ago
- Related to Feature #17000: 2.7.2 turns off deprecation warnings by default added
Updated by byroot (Jean Boussier) 7 months ago
In [Feature #16345] it was stated:
We chose Warning.disable(:deprecated) instead of
re-defining Warning.warn in order to avoid string object generation.
The intent was clearly for Warning.warn
not to be called.
Updated by byroot (Jean Boussier) 7 months ago
On Ruby 2.7.8 when Warning[:deprecated] = false
was introduced:
def Warning.warn(message, **)
p [:warn, message]
end
def foo(a, **b)
[a, b]
end
hash = {bar: 2}
foo(1, hash)
Produces no output, Warning.warn
isn't called. I think this was the intent all along.
Updated by tenderlovemaking (Aaron Patterson) 7 months ago
byroot (Jean Boussier) wrote in #note-6:
In [Feature #16345] it was stated:
We chose Warning.disable(:deprecated) instead of
re-defining Warning.warn in order to avoid string object generation.The intent was clearly for
Warning.warn
not to be called.
I'm reading the ticket the same way. It sounds like this is a bug.
Updated by tenderlovemaking (Aaron Patterson) 7 months ago
- Status changed from Open to Closed
Applied in changeset git|1271ff72d5b627854c6812baefe796a2976cd793.
Don't call Warning.warn
unless the category is enabled
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.
[Bug #20573]
Updated by byroot (Jean Boussier) 7 months ago
- Backport changed from 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN to 3.1: WONTFIX, 3.2: REQUIRED, 3.3: REQUIRED
Given it's a bug fix I think we should mark it for backport. But of course it's up to branch maintainers to decide whether the fix is worth backporting.
Updated by Eregon (Benoit Daloze) 6 months ago ยท Edited
As a small note on this, it's typically better to check $VERBOSE
level and if the category is enabled before even generating/formatting the message String, for performance reasons.
So if that's always done the check in Warning.warn would be basically redundant.
But I agree it makes sense conceptually to check and also in some cases where e.g. the message String is static + frozen and then there is no cost for that message String.
EDIT: I should have looked again at the diff there it's clear the check is done before formatting so makes even more sense (although there can still be cost just to pass the arguments for formatting).
I was thinking this change was checking inside Warning.warn but it checks earlier, all good.
Updated by k0kubun (Takashi Kokubun) 6 months ago
- Backport changed from 3.1: WONTFIX, 3.2: REQUIRED, 3.3: REQUIRED to 3.1: WONTFIX, 3.2: REQUIRED, 3.3: DONE
ruby_3_3 a3eb5e5c70eaee12964cdd807b8f19950003141f.
Updated by nagachika (Tomoyuki Chikanaga) 5 months ago
- Backport changed from 3.1: WONTFIX, 3.2: REQUIRED, 3.3: DONE to 3.1: WONTFIX, 3.2: DONE, 3.3: DONE
ruby_3_2 4f1e047f86b159528055d37ee0da2ad6e5a38c23 merged revision(s) a3eb5e5c70eaee12964cdd807b8f19950003141f.