Skip to content

Commit

Permalink
Use autoload to delay loading features until we need them.
Browse files Browse the repository at this point in the history
This yields about a 10% improvement in the time it
takes to initially load rspec-mocks.
  • Loading branch information
myronmarston committed Feb 23, 2014
1 parent 5fe844e commit 47d398b
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 35 deletions.
31 changes: 31 additions & 0 deletions benchmarks/boot_time.sh
@@ -0,0 +1,31 @@
time (for i in {1..100}; do ruby -Ilib:../rspec-support/lib -rrspec/mocks -e ""; done)

# 3 runs before our autoload changes
# real 0m4.497s
# user 0m3.662s
# sys 0m0.677s
#
# real 0m4.472s
# user 0m3.644s
# sys 0m0.671s
#
# real 0m4.465s
# user 0m3.640s
# sys 0m0.668s

# 3 runs after our autoload changes:
#
# real 0m4.038s
# user 0m3.274s
# sys 0m0.609s
#
# real 0m4.038s
# user 0m3.274s
# sys 0m0.609s
#
# real 0m4.038s
# user 0m3.274s
# sys 0m0.609s

# It's modest, but that's about a 10% improvement: an average
# of about 40ms to load rather than 45 ms to load.
25 changes: 13 additions & 12 deletions lib/rspec/mocks.rb
Expand Up @@ -14,19 +14,7 @@
require 'rspec/mocks/error_generator' require 'rspec/mocks/error_generator'
require 'rspec/mocks/space' require 'rspec/mocks/space'
require 'rspec/mocks/extensions/marshal' require 'rspec/mocks/extensions/marshal'
require 'rspec/mocks/any_instance/chain'
require 'rspec/mocks/any_instance/stub_chain'
require 'rspec/mocks/any_instance/stub_chain_chain'
require 'rspec/mocks/any_instance/expect_chain_chain'
require 'rspec/mocks/any_instance/expectation_chain'
require 'rspec/mocks/any_instance/message_chains'
require 'rspec/mocks/any_instance/recorder'
require 'rspec/mocks/mutate_const' require 'rspec/mocks/mutate_const'
require 'rspec/mocks/matchers/have_received'
require 'rspec/mocks/matchers/receive'
require 'rspec/mocks/matchers/receive_messages'
require 'rspec/mocks/matchers/receive_message_chain'
require 'rspec/mocks/message_chain'
require 'rspec/mocks/targets' require 'rspec/mocks/targets'
require 'rspec/mocks/syntax' require 'rspec/mocks/syntax'
require 'rspec/mocks/configuration' require 'rspec/mocks/configuration'
Expand Down Expand Up @@ -114,5 +102,18 @@ class << self; attr_reader :space; end


# @private # @private
IGNORED_BACKTRACE_LINE = 'this backtrace line is ignored' IGNORED_BACKTRACE_LINE = 'this backtrace line is ignored'

# To speed up boot time a bit, delay loading optional or rarely
# used features until their first use.
autoload :AnyInstance, "rspec/mocks/any_instance"
autoload :ExpectChain, "rspec/mocks/message_chain"
autoload :StubChain, "rspec/mocks/message_chain"

module Matchers
autoload :HaveReceived, "rspec/mocks/matchers/have_received"
autoload :Receive, "rspec/mocks/matchers/receive"
autoload :ReceiveMessageChain, "rspec/mocks/matchers/receive_message_chain"
autoload :ReceiveMessages, "rspec/mocks/matchers/receive_messages"
end
end end
end end
7 changes: 7 additions & 0 deletions lib/rspec/mocks/any_instance.rb
@@ -0,0 +1,7 @@
require 'rspec/mocks/any_instance/chain'
require 'rspec/mocks/any_instance/stub_chain'
require 'rspec/mocks/any_instance/stub_chain_chain'
require 'rspec/mocks/any_instance/expect_chain_chain'
require 'rspec/mocks/any_instance/expectation_chain'
require 'rspec/mocks/any_instance/message_chains'
require 'rspec/mocks/any_instance/recorder'
20 changes: 20 additions & 0 deletions lib/rspec/mocks/matchers/expectation_customization.rb
@@ -0,0 +1,20 @@
module RSpec
module Mocks
module Matchers
# @private
class ExpectationCustomization
attr_accessor :block

def initialize(method_name, args, block)
@method_name = method_name
@args = args
@block = block
end

def playback_onto(expectation)
expectation.__send__(@method_name, *@args, &@block)
end
end
end
end
end
17 changes: 2 additions & 15 deletions lib/rspec/mocks/matchers/receive.rb
@@ -1,3 +1,5 @@
require 'rspec/mocks/matchers/expectation_customization'

module RSpec module RSpec
module Mocks module Mocks
module Matchers module Matchers
Expand Down Expand Up @@ -101,20 +103,5 @@ def move_block_to_last_customization(block)
end end
end end
end end

# @private
class ExpectationCustomization
attr_accessor :block

def initialize(method_name, args, block)
@method_name = method_name
@args = args
@block = block
end

def playback_onto(expectation)
expectation.__send__(@method_name, *@args, &@block)
end
end
end end
end end
2 changes: 2 additions & 0 deletions lib/rspec/mocks/matchers/receive_message_chain.rb
@@ -1,3 +1,5 @@
require 'rspec/mocks/matchers/expectation_customization'

module RSpec module RSpec
module Mocks module Mocks
module Matchers module Matchers
Expand Down
9 changes: 1 addition & 8 deletions lib/rspec/mocks/targets.rb
Expand Up @@ -37,16 +37,9 @@ def self.disallow_negation(method_name)
private private


def matcher_allowed?(matcher) def matcher_allowed?(matcher)
ALLOWED_MATCHERS.include?(matcher.class) matcher.class.name.start_with?("RSpec::Mocks::Matchers".freeze)
end end


#@api private
ALLOWED_MATCHERS = [
Matchers::Receive,
Matchers::ReceiveMessages,
Matchers::ReceiveMessageChain,
]

def define_matcher(matcher, name, &block) def define_matcher(matcher, name, &block)
matcher.__send__(name, @target, &block) matcher.__send__(name, @target, &block)
end end
Expand Down

0 comments on commit 47d398b

Please sign in to comment.