From 69de09c5cee19d63400c4b62d2ebeac5a89eb14d Mon Sep 17 00:00:00 2001
From: Guo Xiang Tan <tgx_world@hotmail.com>
Date: Mon, 7 Sep 2015 15:13:00 +0800
Subject: PERF: Don't create a Relation when it is not needed.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Benchmark script used:
```
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('all') { User.all }
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 -------------------------------------
                 all    17.569k i/100ms
-------------------------------------------------
                 all    190.854k (± 3.3%) i/s -    966.295k
Total Allocated Object: 85
```

After:
```
Calculating -------------------------------------
                 all    22.237k i/100ms
-------------------------------------------------
                 all    262.715k (± 5.5%) i/s -      1.312M
Total Allocated Object: 80
```
---
 activerecord/lib/active_record/scoping/default.rb | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb
index a1adf8e3ee..6454f17fdb 100644
--- a/activerecord/lib/active_record/scoping/default.rb
+++ b/activerecord/lib/active_record/scoping/default.rb
@@ -99,12 +99,13 @@ module ActiveRecord
           self.default_scopes += [scope]
         end
 
-        def build_default_scope(base_rel = relation) # :nodoc:
+        def build_default_scope(base_rel = nil) # :nodoc:
           return if abstract_class?
           if !Base.is_a?(method(:default_scope).owner)
             # The user has defined their own default scope method, so call that
             evaluate_default_scope { default_scope }
           elsif default_scopes.any?
+            base_rel ||= relation
             evaluate_default_scope do
               default_scopes.inject(base_rel) do |default_scope, scope|
                 default_scope.merge(base_rel.scoping { scope.call })
-- 
cgit v1.2.3