-
Notifications
You must be signed in to change notification settings - Fork 404
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
Improve performance by moving template compilation from #render_in
to #render_template_for
#1302
Conversation
…to `#render_template_for`
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.
This is awesome 🤩
15% is not an everyday gain 🙌
Left a comment on how we can rely on inheritance in order to avoid the re-definition.
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.
Awesome, left a few nits
But pre-approving in the meantime 👍
**Why**: 15% render performance bump, according to ViewComponent/view_component#1302 . changelog: Internal, Dependencies, Update dependencies to latest version
**Why**: 15% render performance bump, according to ViewComponent/view_component#1302 . changelog: Internal, Dependencies, Update dependencies to latest version
Summary
Currently, every call to
#render_in
callsself.class.compile
, which compiles the template and attaches a new#render_template_for
method to the component's class. If the template has already been compiled and cached, the compiler skips compilation and returns immediately.While calling
.compile
may at first appear innocuous, it requires four or five method calls that essentially do nothing every time (except the first) the component is rendered. These method calls are pure overhead.This PR moves the
.compile
call from#render_in
to a temporary#render_template_for
method. This temporary method invokes the compiler (which replaces#render_template_for
with the compiled version), then calls the compiled version. At first glance it looks like recursion 😜Because the code that invokes the compiler is replaced on first render, cache invalidation needs to work a little differently. Instead of simply clearing the cache, the old stub methods also must be added back into the component classes. I agree it's a little unorthodox, but thanks to Ruby's flexibility it works pretty well. To my knowledge, cache invalidation is only used in dev and test environments anyway, so all this additional dynamic method stuff shouldn't affect prod environments.
Other Information
The performance impact of the change is fairly significant.
Main
This branch
That's a 15% speedup 😄