Open jacobobq opened 2 months ago
This makes sense to me. I recently saw a PR in rails (https://github.com/rails/rails/pull/52449#discussion_r1696875349) about the same thing with instance methods.
The same thing can also apply for constants
=> const_defined?
, class_variables
=> class_variable_defined?
, *class_methods
=> *class_method_defined?
, though I have neither tested performance nor checked if there are subtle differences between these versions.
It would be nice if this can also regognize [foo.methods + foo.private_methods].include?
=> foo.method_defined? || foo.private_method_defined?
but for a first implementation not necessary.
Is your feature request related to a problem? Please describe.
We've found some instances of bad performance related to calling include? directly over the result of
Kernel#methods
. This can be answered more efficiently by callingObject#respond_to?
.Here's a benchmark for the difference in my system.
dummies
is an array of 1000 empty structs, whilemethods
is an array of 1000 randomly generated symbols 5 lowercase letter characters in length.The difference between calling
methods.include?
and usingrespond_to?
accounts for a full order of magnitude in real time. Similarly, it's shown that if you are repeatedly checking for different methods over the same class, creating and querying a set with the result ofmethods
will provide an additional performance boost.For the reasons stated above, I think it'd be useful to detect cases where this happens and provide a warning to programmers.
Describe the solution you'd like
A rubocop cop that detects
methods.include?(:x)
andpublic_methods.include?(:x)
and suggestsrespond_to?(:x, true)
andrespond_to?(:x, false)
respectively.Describe alternatives you've considered
I cannot think of alternative solutions besides not doing this.
Additional context
The system where I run the benchmark was a MacBook Pro with the Apple M2 chip and 16 GB of RAM memory. The Ruby version was Ruby 3.3.3.