-
Notifications
You must be signed in to change notification settings - Fork 133
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
Call to_a
on cached ObjectSpace
enumerator
#2073
Conversation
I have signed the CLA! |
to_a
on cached ObjectSpace
enumerator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your contribution! I have 2 small suggestions, but otherwise LGTM!
Once you ship this, I'll do a quick benchmark against our monolith. I'm expecting there should be pretty substantial gains!
lib/tapioca/dsl/compiler.rb
Outdated
ObjectSpace.each_object(Class) | ||
end, | ||
T.cast( | ||
all_modules.select { |k| k.is_a?(Class) }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's kind of niche, but .grep(Class)
is noticeably faster (last I benchmarked it), since it calls Class#===
directly, without needing the overhead of a block call like select
needs
all_modules.select { |k| k.is_a?(Class) }, | |
all_modules.grep(Class), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually didn't know this! Good to know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to know.
It's cursed knowledge, as Aaron would say
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 other nice benefits:
- It removes the need for this cast because
Enumerable#grep
has a special overload for metatypes. - The
k.is_a?(Class)
was callingis_a?
onk
, which could be arbitrary user code that breaks things.Class === k
would always be on a receiver we control,Class
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, @amomchilov is spot on, especially around the use of ===
. In this project, we prefer to use ===
over is_a?
whenever it is possible, since the receiver of ===
is usually under our control, so the result can be more dependable.
lib/tapioca/dsl/compiler.rb
Outdated
@@ -89,7 +88,7 @@ def all_modules | |||
if @@requested_constants.any? | |||
@@requested_constants.select { |k| k.is_a?(Module) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May as well change this too, to be consistent.
@@requested_constants.select { |k| k.is_a?(Module) } | |
@@requested_constants.grep(Module) |
220445b
to
85751a5
Compare
85751a5
to
2dfbfa4
Compare
Tested on our monolith, works great. We'll merge once we sort our CI issues |
Rebased to get CI fixes! |
Based on the existence of the
@@requested_contants
code path, it seems safe for this method to return anArray
in some cases, so simply caching the array of allModules
rather than the enumerator should be safe. Also, I have included the recommended optimization to deriveall_classes
fromall_modules
, which both simplifies things (no need for the@@requested_constants
code path in both methods), as well as improves performance by skipping a full ObjectSpace traversal again.Motivation
Closes #1974
Tests
This is simply an optimization to an existing tested behavior.