diff options
author | Guo Xiang Tan <tgx_world@hotmail.com> | 2015-09-06 08:49:35 +0800 |
---|---|---|
committer | Guo Xiang Tan <tgx_world@hotmail.com> | 2015-09-07 12:39:16 +0800 |
commit | 47e06c988e8377d04a6a6e28e798b06187326d87 (patch) | |
tree | 0e658f00592434e18d0ff2120ed71d4f69ce3ce5 | |
parent | f1f0a3f8d99aef8aacfa81ceac3880dcac03ca06 (diff) | |
download | rails-47e06c988e8377d04a6a6e28e798b06187326d87.tar.gz rails-47e06c988e8377d04a6a6e28e798b06187326d87.tar.bz2 rails-47e06c988e8377d04a6a6e28e798b06187326d87.zip |
Reduce calls to stringify_keys.
Stackprof output truncated.
```
TOTAL (pct) SAMPLES (pct) FRAME
23 (4.7%) 12 (2.4%) Hash#transform_keys
11 (2.2%) 11 (2.2%) block in Hash#transform_keys
30 (6.1%) 7 (1.4%) Hash#stringify_keys
```
Benchmark Script:
```
begin
require 'bundler/inline'
rescue LoadError => e
$stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true) do
source 'https://rubygems.org'
gem 'rails', path: '~/rails' # master against ref "f1f0a3f8d99aef8aacfa81ceac3880dcac03ca06"
gem 'arel', github: 'rails/arel', branch: 'master'
gem 'rack', github: 'rack/rack', branch: 'master'
gem 'sass'
gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: 'master'
gem 'sprockets', github: 'rails/sprockets', branch: 'master'
gem 'pg'
gem 'benchmark-ips'
end
require 'active_record'
require 'benchmark/ips'
ActiveRecord::Base.establish_connection('postgres://postgres@localhost:5432/rubybench')
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define do
create_table :users, force: true do |t|
t.string :name, :email
t.timestamps null: false
end
end
class User < ActiveRecord::Base; end
attributes = {
name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
email: "foobar@email.com",
}
1000.times { User.create!(attributes) }
Benchmark.ips(5, 3) do |x|
x.report('where with hash') { User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") }
x.report('where with string') { User.where("users.name = ?", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") }
x.compare!
end
key =
if RUBY_VERSION < '2.2'
:total_allocated_object
else
:total_allocated_objects
end
before = GC.stat[key]
User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
after = GC.stat[key]
puts "Total Allocated Object: #{after - before}"
```
Before:
```
Calculating -------------------------------------
where with hash 2.796k i/100ms
where with string 4.338k i/100ms
-------------------------------------------------
where with hash 29.177k (± 1.5%) i/s - 148.188k
where with string 47.419k (± 2.8%) i/s - 238.590k
Comparison:
where with string: 47419.0 i/s
where with hash: 29176.6 i/s - 1.63x slower
Total Allocated Object: 85
```
After:
```
Calculating -------------------------------------
where with hash 2.895k i/100ms
where with string 4.416k i/100ms
-------------------------------------------------
where with hash 30.758k (± 2.0%) i/s - 156.330k
where with string 47.708k (± 2.6%) i/s - 238.464k
Comparison:
where with string: 47707.9 i/s
where with hash: 30757.7 i/s - 1.55x slower
Total Allocated Object: 84
```
3 files changed, 5 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index d26db7d4cf..e232516b0c 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -24,12 +24,12 @@ module ActiveRecord end def build_from_hash(attributes) - attributes = convert_dot_notation_to_hash(attributes.stringify_keys) + attributes = convert_dot_notation_to_hash(attributes) expand_from_hash(attributes) end def create_binds(attributes) - attributes = convert_dot_notation_to_hash(attributes.stringify_keys) + attributes = convert_dot_notation_to_hash(attributes) create_binds_for_hash(attributes) end diff --git a/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb index 159889d3b8..e81be63cd3 100644 --- a/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb +++ b/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb @@ -10,10 +10,10 @@ module ActiveRecord table = value.associated_table if value.base_class - queries[table.association_foreign_type] = value.base_class.name + queries[table.association_foreign_type.to_s] = value.base_class.name end - queries[table.association_foreign_key] = value.ids + queries[table.association_foreign_key.to_s] = value.ids predicate_builder.build_from_hash(queries) end diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb index 0430922be3..23eaab4699 100644 --- a/activerecord/lib/active_record/relation/where_clause_factory.rb +++ b/activerecord/lib/active_record/relation/where_clause_factory.rb @@ -15,6 +15,7 @@ module ActiveRecord when Hash attributes = predicate_builder.resolve_column_aliases(opts) attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes) + attributes.stringify_keys! attributes, binds = predicate_builder.create_binds(attributes) |