Improve performance of blank? and present? in an ActiveRecord::Base instance

With this benchmark:

    require "bundler/setup"

    require "active_record"
    require "benchmark/ips"

    # This connection will do for database-independent bug reports.
    ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")

    ActiveRecord::Schema.define do
      create_table :posts, force: true do |t|
      end
    end

    class Post < ActiveRecord::Base
    end

    new_post = Post.new

    Benchmark.ips do |b|
      b.report("present?") do
        new_post.present?
      end

      b.report("blank?") do
        new_post.blank?
      end
    end

Before:

    Warming up --------------------------------------
                present?    52.147k i/100ms
                  blank?    53.077k i/100ms
    Calculating -------------------------------------
                present?    580.184k (±21.8%) i/s -      2.555M in   5.427085s
                  blank?    601.537k (± 9.2%) i/s -      2.972M in   5.003503s

After:

    Warming up --------------------------------------
                present?   378.235k i/100ms
                  blank?   375.476k i/100ms
    Calculating -------------------------------------
                present?     17.381M (± 7.5%) i/s -     86.238M in   5.001815s
                  blank?     17.877M (± 6.4%) i/s -     88.988M in   5.004634s

This improvement is mostly because those methods were hitting
`method_missing` on a lot of levels to be able to return the value.

To avoid all this stack walking we are short-circuiting those methods.

Closes #35059.
上级 2299d31c
......@@ -477,6 +477,14 @@ def <=>(other_object)
end
end
def present? # :nodoc:
true
end
def blank? # :nodoc:
false
end
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
# attributes will be marked as read only since they cannot be saved.
def readonly?
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册