1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

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
```
This commit is contained in:
Guo Xiang Tan 2015-09-06 08:49:35 +08:00
parent f1f0a3f8d9
commit 47e06c988e
3 changed files with 5 additions and 4 deletions

View file

@ -24,12 +24,12 @@ module ActiveRecord
end end
def build_from_hash(attributes) 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) expand_from_hash(attributes)
end end
def create_binds(attributes) 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) create_binds_for_hash(attributes)
end end

View file

@ -10,10 +10,10 @@ module ActiveRecord
table = value.associated_table table = value.associated_table
if value.base_class 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 end
queries[table.association_foreign_key] = value.ids queries[table.association_foreign_key.to_s] = value.ids
predicate_builder.build_from_hash(queries) predicate_builder.build_from_hash(queries)
end end

View file

@ -15,6 +15,7 @@ module ActiveRecord
when Hash when Hash
attributes = predicate_builder.resolve_column_aliases(opts) attributes = predicate_builder.resolve_column_aliases(opts)
attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes) attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes)
attributes.stringify_keys!
attributes, binds = predicate_builder.create_binds(attributes) attributes, binds = predicate_builder.create_binds(attributes)