-
Notifications
You must be signed in to change notification settings - Fork 526
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 of method call via delegate_all
#911
Merged
y-yagi
merged 2 commits into
drapergem:master
from
y-yagi:improve-delegate_all-performance
Sep 4, 2024
Merged
Improve performance of method call via delegate_all
#911
y-yagi
merged 2 commits into
drapergem:master
from
y-yagi:improve-delegate_all-performance
Sep 4, 2024
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
y-yagi
force-pushed
the
improve-delegate_all-performance
branch
from
December 14, 2021 01:57
0ed9c96
to
adb4fc8
Compare
Failed test is unrelated with this change. That test will fix by #912. |
y-yagi
force-pushed
the
improve-delegate_all-performance
branch
from
December 16, 2021 23:31
adb4fc8
to
5a03248
Compare
Rebased with master and now CI passes. |
y-yagi
added a commit
to ClinicalPlatform/draper
that referenced
this pull request
Dec 20, 2021
Currently, `delegatable?` call `private_methods` to check method is private or not. The `private_methods` generates an Array of methods per call. So a method call via `delegate_all` generates an extra Array every time. This patch use `private_method_defined?` instead of `private_methods`. This reduce the extra Array. The inherit argument for `private_method_defined?` is supported since Ruby 2.6. So this patch only works for >= Ruby 2.6. Rubies old than Ruby 2.6 keep using `private_methods`. Ref: https://bugs.ruby-lang.org/issues/14944 Benchmark is here. ```ruby require "bundler/inline" gemfile(true) do source "https://rubygems.org" gem "activerecord" gem "sqlite3" if ENV["USE_FORKED_GEM"] gem "draper", github: "y-yagi/draper", branch: "improve-delegate_all-performance" else gem "draper" end gem "benchmark-ips" end require "active_record" require "logger" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Base.logger = nil ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, null: false t.timestamps end end ActiveRecord::Base.logger = Logger.new(STDOUT) class User < ActiveRecord::Base end class UserDecorator < Draper::Decorator delegate_all def decorated_name "'#{name}'" end end User.create!(name: "Dummy User") u = UserDecorator.decorate(User.first) Benchmark.ips do |x| x.report(ENV["USE_FORKED_GEM"] == "true" ? "forked draper" : "released draper") do 1000.times { u.decorated_name } end x.save! ENV["SAVE_FILE"] if ENV["SAVE_FILE"] x.compare! end ``` ```bash $ SAVE_FILE=result.out ruby draper.rb $ USE_FORKED_GEM=true SAVE_FILE=result.out ruby draper.rb ... Comparison: forked draper: 454.5 i/s released draper: 63.8 i/s - 7.12x (± 0.00) slower ``` This is a fork of drapergem#911
Currently, `delegatable?` call `private_methods` to check method is private or not. The `private_methods` generates an Array of methods per call. So a method call via `delegate_all` generates an extra Array every time. This patch use `private_method_defined?` instead of `private_methods`. This reduce the extra Array. The inherit argument for `private_method_defined?` is supported since Ruby 2.6. So this patch only works for >= Ruby 2.6. Rubies old than Ruby 2.6 keep using `private_methods`. Ref: https://bugs.ruby-lang.org/issues/14944 Benchmark is here. ```ruby require "bundler/inline" gemfile(true) do source "https://rubygems.org" gem "activerecord" gem "sqlite3" if ENV["USE_FORKED_GEM"] gem "draper", github: "y-yagi/draper", branch: "improve-delegate_all-performance" else gem "draper" end gem "benchmark-ips" end require "active_record" require "logger" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Base.logger = nil ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, null: false t.timestamps end end ActiveRecord::Base.logger = Logger.new(STDOUT) class User < ActiveRecord::Base end class UserDecorator < Draper::Decorator delegate_all def decorated_name "'#{name}'" end end User.create!(name: "Dummy User") u = UserDecorator.decorate(User.first) Benchmark.ips do |x| x.report(ENV["USE_FORKED_GEM"] == "true" ? "forked draper" : "released draper") do 1000.times { u.decorated_name } end x.save! ENV["SAVE_FILE"] if ENV["SAVE_FILE"] x.compare! end ``` ```bash $ SAVE_FILE=result.out ruby draper.rb $ USE_FORKED_GEM=true SAVE_FILE=result.out ruby draper.rb ... Comparison: forked draper: 454.5 i/s released draper: 63.8 i/s - 7.12x (± 0.00) slower ```
y-yagi
force-pushed
the
improve-delegate_all-performance
branch
from
August 25, 2024 02:09
5a03248
to
2d53439
Compare
Alexander-Senko
approved these changes
Aug 30, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Currently,
delegatable?
callprivate_methods
to check method is private or not. Theprivate_methods
generates an Array of methods per call. So a method call viadelegate_all
generates an extra Array every time.This patch use
private_method_defined?
instead ofprivate_methods
. This reduce the extra Array.The inherit argument for
private_method_defined?
is supported since Ruby 2.6.So this patch only works for >= Ruby 2.6. Rubies old than Ruby 2.6 keep using
private_methods
.Ref: https://bugs.ruby-lang.org/issues/14944
Benchmark is here.
Testing
Existing tests covers this change.