1. 25 10月, 2014 1 次提交
    • D
      Use type column first in multi-column indexes · 9cdd0a1f
      Derek Prior 提交于
      `add_reference` can very helpfully add a multi-column index when you use
      it to add a polymorphic reference. However, the first column in the
      index is the `id` column, which is less than ideal.
      
      The [PostgreSQL docs][1] say:
      > A multicolumn B-tree index can be used with query conditions that
      > involve any subset of the index's columns, but the index is most
      > efficient when there are constraints on the leading (leftmost)
      > columns.
      
      The [MySQL docs][2] say:
      > MySQL can use multiple-column indexes for queries that test all the
      > columns in the index, or queries that test just the first column, the
      > first two columns, the first three columns, and so on. If you specify
      > the columns in the right order in the index definition, a single
      > composite index can speed up several kinds of queries on the same
      > table.
      
      In a polymorphic relationship, the type column is much more likely to be
      useful as the first column in an index than the id column. That is, I'm
      more likely to query on type without an id than I am to query on id
      without a type.
      
      [1]: http://www.postgresql.org/docs/9.3/static/indexes-multicolumn.html
      [2]: http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html
      9cdd0a1f
  2. 21 10月, 2014 1 次提交
    • C
      Remove duplicate 'select' database statement · ec981aa1
      claudiob 提交于
      The `select` method has the same definition in almost all database
      adapters, so it can be moved from the database-specific adapters
      (PostgreSQl, MySQL, SQLite) to the abstract `database_statement`:
      
      ```ruby
      def select(sql, name = nil, binds = [])
        exec_query(sql, name, binds)
      end
      ```
      
      ---
      
      More details about this commit: the only two DB-specific adapters
      that have a different definition of `select` are MySQLAdapter and
      MySQL2Adapter.
      
      In MySQLAdapter, `select` invokes `exec_query(sql, name, binds)`, so
      calling `super` achieves the same goal with less repetition.
      
      In MySQL2Adapter, `select` invokes `exec_query(sql, name)`, that is,
      it does not pass the `binds` parameter like other methods do. However,
      [MySQL2Adapter's `exec_query`](https://github.com/rails/rails/blob/74a527cc63ef56f3d0a42cf638299958dc7cb08c/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb#L228L231)
      works exactly the same whether this parameters is passed or not, so the output
      does not change:
      
      ```ruby
      def exec_query(sql, name = 'SQL', binds = [])
        result = execute(sql, name)
        ActiveRecord::Result.new(result.fields, result.to_a)
      end
      ```
      ec981aa1
  3. 20 10月, 2014 4 次提交
  4. 19 10月, 2014 3 次提交
  5. 18 10月, 2014 1 次提交
    • C
      Replace (slower) block.call with (faster) yield · 6aa115e4
      claudiob 提交于
      Performance optimization: `yield` with an implicit `block` is faster than `block.call`.
      See http://youtu.be/fGFM_UrSp70?t=10m35s and the following benchmark:
      
      ```ruby
      require 'benchmark/ips'
      
      def fast
       yield
      end
      
      def slow(&block)
       block.call
      end
      
      Benchmark.ips do |x|
       x.report('fast') { fast{} }
       x.report('slow') { slow{} }
      end
      
      # => fast    154095 i/100ms
      # => slow     71454 i/100ms
      # =>
      # => fast  7511067.8 (±5.0%) i/s -   37445085 in   4.999660s
      # => slow  1227576.9 (±6.8%) i/s -    6145044 in   5.028356s
      ```
      6aa115e4
  6. 17 10月, 2014 1 次提交
    • S
      Add a deprecation warning for abiguous boolean values · e01a46f1
      Sean Griffin 提交于
      In Rails 5.0, we'd like to change the behavior of boolean columns in
      Rails to be closer to Ruby's semantics. Currently we have a small set
      of values which are "truthy", and all others are "falsy". In Rails 5.0,
      we will reverse this to have a small number of values which are "falsy",
      and all others will become "truthy".
      
      In the interim, all values which are ambiguous must emit a deprecation
      warning.
      e01a46f1
  7. 16 10月, 2014 8 次提交
  8. 15 10月, 2014 6 次提交
  9. 14 10月, 2014 4 次提交
  10. 13 10月, 2014 2 次提交
  11. 07 10月, 2014 1 次提交
  12. 06 10月, 2014 2 次提交
  13. 04 10月, 2014 1 次提交
  14. 01 10月, 2014 1 次提交
  15. 29 9月, 2014 3 次提交
    • E
      Use Hash#each_key instead of Hash#keys.each · e2b49b20
      Erik Michaels-Ober 提交于
      Hash#keys.each allocates an array of keys; Hash#each_key iterates through the
      keys without allocating a new array. This is the reason why Hash#each_key
      exists.
      e2b49b20
    • B
      Remove defunct ivars · 588c321e
      Ben Woosley 提交于
      @column_names_with_alias, @dynamic_methods_hash, @time_zone_column_names, and @cached_time_zone
      588c321e
    • P
      Reduce allocations when running AR callbacks. · 796cab45
      Pete Higgins 提交于
      Inspired by @tenderlove's work in
      c363fff2, this reduces the number of
      strings allocated when running callbacks for ActiveRecord instances. I
      measured that using this script:
      
      ```
      require 'objspace'
      require 'active_record'
      require 'allocation_tracer'
      
      ActiveRecord::Base.establish_connection adapter: "sqlite3",
                                              database: ":memory:"
      
      ActiveRecord::Base.connection.instance_eval do
        create_table(:articles) { |t| t.string :name }
      end
      
      class Article < ActiveRecord::Base; end
      a = Article.create name: "foo"
      a = Article.find a.id
      
      N = 10
      result = ObjectSpace::AllocationTracer.trace do
        N.times { Article.find a.id }
      end
      
      result.sort.each do |k,v|
        p k => v
      end
      puts "total: #{result.values.map(&:first).inject(:+)}"
      ```
      
      When I run this against master and this branch I get this output:
      
      ```
      pete@balloon:~/projects/rails/activerecord$ git checkout master
      M Gemfile
      Switched to branch 'master'
      pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_before
      pete@balloon:~/projects/rails/activerecord$ git checkout remove-dynamic-send-on-built-in-callbacks
      M Gemfile
      Switched to branch 'remove-dynamic-send-on-built-in-callbacks'
      pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_after
      pete@balloon:~/projects/rails/activerecord$ diff allocations_before allocations_after
      39d38
      <
      {["/home/pete/projects/rails/activesupport/lib/active_support/callbacks.rb",
      81]=>[40, 0, 0, 0, 0, 0]}
      42c41
      < total: 630
      ---
      > total: 590
      
      ```
      
      In addition to this, there are two micro-optimizations present:
      
      * Using `block.call if block` vs `yield if block_given?` when the block was being captured already.
      
      ```
      pete@balloon:~/projects$ cat benchmark_block_call_vs_yield.rb
      require 'benchmark/ips'
      
      def block_capture_with_yield &block
        yield if block_given?
      end
      
      def block_capture_with_call &block
        block.call if block
      end
      
      def no_block_capture
        yield if block_given?
      end
      
      Benchmark.ips do |b|
        b.report("block_capture_with_yield") { block_capture_with_yield }
        b.report("block_capture_with_call") { block_capture_with_call }
        b.report("no_block_capture") { no_block_capture }
      end
      pete@balloon:~/projects$ ruby benchmark_block_call_vs_yield.rb
      Calculating -------------------------------------
      block_capture_with_yield
                              124979 i/100ms
      block_capture_with_call
                              138340 i/100ms
          no_block_capture    136827 i/100ms
      -------------------------------------------------
      block_capture_with_yield
                            5703108.9 (±2.4%) i/s -   28495212 in   4.999368s
      block_capture_with_call
                            6840730.5 (±3.6%) i/s -   34169980 in   5.002649s
          no_block_capture  5821141.4 (±2.8%) i/s -   29144151 in   5.010580s
      ```
      
      * Defining and calling methods instead of using send.
      
      ```
      pete@balloon:~/projects$ cat benchmark_method_call_vs_send.rb
      require 'benchmark/ips'
      
      class Foo
        def tacos
          nil
        end
      end
      
      my_foo = Foo.new
      
      Benchmark.ips do |b|
        b.report('send') { my_foo.send('tacos') }
        b.report('call') { my_foo.tacos }
      end
      pete@balloon:~/projects$ ruby benchmark_method_call_vs_send.rb
      Calculating -------------------------------------
                      send     97736 i/100ms
                      call    151142 i/100ms
      -------------------------------------------------
                      send  2683730.3 (±2.8%) i/s -   13487568 in   5.029763s
                      call  8005963.9 (±2.7%) i/s -   40052630 in   5.006604s
      ```
      
      The result of this is making typical ActiveRecord operations slightly faster:
      
      https://gist.github.com/phiggins/e46e51dcc7edb45b5f98
      796cab45
  16. 28 9月, 2014 1 次提交
    • R
      Follow up to #16613 · 1fac7b79
      Robin Dupret 提交于
      Since we want this flag to be enabled anytime we are running the tests
      under JRuby, let's enable this at the Rakefile level so people get the
      performance boost on their local checkout.
      
      Moreover, we avoid having to update this particular line anytime the
      option changes on the JRuby side.
      
      The only drawback is that we have to define it in every Rakefile but
      there's no big deal, this is already the case for other options.
      1fac7b79