提交 a1d236e9 编写于 作者: R Ryuta Kamizono

Make predicate builder about 2x faster

Extra predicate handler for just one line preprocess is too expensive.

```ruby
ActiveRecord::Schema.define do
  create_table :users, force: true do |t|
  end
end

class User < ActiveRecord::Base
end

predicate_builder = User.predicate_builder

attr = User.arel_attribute(:id)
user = User.create!
user_id = user.id

Benchmark.ips do |x|
  x.report("build:user") { predicate_builder.build(attr, user) }
  x.report("build:user_id") { predicate_builder.build(attr, user_id) }
end
```

Before:

```
Warming up --------------------------------------
          build:user    11.626k i/100ms
       build:user_id    23.314k i/100ms
Calculating -------------------------------------
          build:user    114.151k (± 2.0%) i/s -    581.300k in   5.094468s
       build:user_id    226.420k (± 2.3%) i/s -      1.142M in   5.048205s
```

After:

```
Warming up --------------------------------------
          build:user    21.484k i/100ms
       build:user_id    24.307k i/100ms
Calculating -------------------------------------
          build:user    210.207k (± 1.8%) i/s -      1.053M in   5.009623s
       build:user_id    238.276k (± 2.1%) i/s -      1.215M in   5.102951s
```
上级 159cc342
......@@ -7,7 +7,6 @@ def initialize(table)
@handlers = []
register_handler(BasicObject, BasicObjectHandler.new(self))
register_handler(Base, BaseHandler.new(self))
register_handler(Range, RangeHandler.new(self))
register_handler(Relation, RelationHandler.new)
register_handler(Array, ArrayHandler.new(self))
......@@ -48,6 +47,7 @@ def register_handler(klass, handler)
end
def build(attribute, value)
value = value.id if value.is_a?(Base)
if table.type(attribute.name).force_equality?(value)
bind = build_bind_attribute(attribute.name, value)
attribute.eq(bind)
......@@ -158,7 +158,6 @@ def handler_for(object)
end
require "active_record/relation/predicate_builder/array_handler"
require "active_record/relation/predicate_builder/base_handler"
require "active_record/relation/predicate_builder/basic_object_handler"
require "active_record/relation/predicate_builder/range_handler"
require "active_record/relation/predicate_builder/relation_handler"
......
# frozen_string_literal: true
module ActiveRecord
class PredicateBuilder
class BaseHandler # :nodoc:
def initialize(predicate_builder)
@predicate_builder = predicate_builder
end
def call(attribute, value)
predicate_builder.build(attribute, value.id)
end
private
attr_reader :predicate_builder
end
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册