-
Couldn't load subscription status.
- Fork 528
Improve performance of method call via delegate_all
#911
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
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 hidden or 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
0ed9c96 to
adb4fc8
Compare
|
Failed test is unrelated with this change. That test will fix by #912. |
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 ```
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_methodsto check method is private or not. Theprivate_methodsgenerates an Array of methods per call. So a method call viadelegate_allgenerates 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.
$ 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) slowerTesting
Existing tests covers this change.