diff --git a/benchmarks/boot_time_with_many_load_path_dirs.sh b/benchmarks/boot_time_with_many_load_path_dirs.sh new file mode 100755 index 0000000000..09f5a8820a --- /dev/null +++ b/benchmarks/boot_time_with_many_load_path_dirs.sh @@ -0,0 +1,123 @@ +ruby -v + +function run_benchmark_with_load_path_size { + pushd tmp + mkdir -p boot_time_benchmark + + local load_path_size=$1 + for (( i=0; i < $load_path_size; i++ )); do + mkdir -p "boot_time_benchmark/dir_$i" + done + + local load_path=`ruby -e 'puts Array.new(Integer(ARGV.first)) { |i| "boot_time_benchmark/dir_#{i}" }.join(":")' $load_path_size` + + echo "3 runs with $load_path_size dirs on load path, booting 50 times, using $2" + for i in {1..3}; do + time (for i in {1..50}; do ruby -I$load_path:../lib:../../rspec-support/lib -e 'require "rspec/core"'; done) + done + popd +} + +run_benchmark_with_load_path_size 10 "require" +run_benchmark_with_load_path_size 100 "require" +run_benchmark_with_load_path_size 1000 "require" + +export REQUIRE_RELATIVE=1 + +run_benchmark_with_load_path_size 10 "require_relative" +run_benchmark_with_load_path_size 100 "require_relative" +run_benchmark_with_load_path_size 1000 "require_relative" + +: <<'result_comment' +ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0] +~/code/rspec-core/tmp ~/code/rspec-core +3 runs with 10 dirs on load path, booting 50 times, using require + +real 0m3.815s +user 0m3.205s +sys 0m0.519s + +real 0m3.850s +user 0m3.234s +sys 0m0.527s + +real 0m3.840s +user 0m3.225s +sys 0m0.525s +~/code/rspec-core +~/code/rspec-core/tmp ~/code/rspec-core +3 runs with 100 dirs on load path, booting 50 times, using require + +real 0m5.086s +user 0m3.887s +sys 0m1.107s + +real 0m5.063s +user 0m3.870s +sys 0m1.098s + +real 0m5.061s +user 0m3.871s +sys 0m1.097s +~/code/rspec-core +~/code/rspec-core/tmp ~/code/rspec-core +3 runs with 1000 dirs on load path, booting 50 times, using require + +real 0m18.850s +user 0m11.057s +sys 0m7.679s + +real 0m18.783s +user 0m11.012s +sys 0m7.657s + +real 0m18.747s +user 0m10.992s +sys 0m7.639s +~/code/rspec-core +~/code/rspec-core/tmp ~/code/rspec-core +3 runs with 10 dirs on load path, booting 50 times, using require_relative + +real 0m3.794s +user 0m3.200s +sys 0m0.506s + +real 0m3.769s +user 0m3.180s +sys 0m0.502s + +real 0m3.787s +user 0m3.192s +sys 0m0.502s +~/code/rspec-core +~/code/rspec-core/tmp ~/code/rspec-core +3 runs with 100 dirs on load path, booting 50 times, using require_relative + +real 0m4.626s +user 0m3.620s +sys 0m0.910s + +real 0m4.652s +user 0m3.642s +sys 0m0.915s + +real 0m4.678s +user 0m3.662s +sys 0m0.924s +~/code/rspec-core +~/code/rspec-core/tmp ~/code/rspec-core +3 runs with 1000 dirs on load path, booting 50 times, using require_relative + +real 0m14.400s +user 0m8.615s +sys 0m5.675s + +real 0m14.495s +user 0m8.672s +sys 0m5.711s + +real 0m14.541s +user 0m8.705s +sys 0m5.727s +~/code/rspec-core +result_comment diff --git a/benchmarks/require_relative_v_require.rb b/benchmarks/require_relative_v_require.rb index 944f74868e..04a5bafd8b 100644 --- a/benchmarks/require_relative_v_require.rb +++ b/benchmarks/require_relative_v_require.rb @@ -49,3 +49,27 @@ # virtually no penalty # # ################################### + +__END__ + +Ruby 2.0: + +➜ rspec-core git:(benchmark-require-relative) REQUIRE_RELATIVE=1 bundle exec ruby benchmarks/require_relative_v_require.rb + 0.000000 0.030000 1.470000 ( 1.481949) + 0.000000 0.020000 1.440000 ( 1.462620) + 0.000000 0.020000 1.470000 ( 1.491825) +➜ rspec-core git:(benchmark-require-relative) bundle exec ruby benchmarks/require_relative_v_require.rb + 0.000000 0.010000 1.510000 ( 1.549906) + 0.000000 0.010000 1.530000 ( 1.546252) + 0.000000 0.020000 1.510000 ( 1.531644) + +Ruby 2.1: + +➜ rspec-core git:(benchmark-require-relative) bundle exec ruby benchmarks/require_relative_v_require.rb + 0.000000 0.020000 1.570000 ( 1.613217) + 0.000000 0.020000 1.600000 ( 1.618540) + 0.010000 0.020000 1.570000 ( 1.608205) +➜ rspec-core git:(benchmark-require-relative) REQUIRE_RELATIVE=1 bundle exec ruby benchmarks/require_relative_v_require.rb + 0.000000 0.020000 1.480000 ( 1.515131) + 0.000000 0.010000 1.480000 ( 1.527766) + 0.000000 0.020000 1.490000 ( 1.515631) diff --git a/lib/rspec/core.rb b/lib/rspec/core.rb index f43032081e..c4251c9111 100644 --- a/lib/rspec/core.rb +++ b/lib/rspec/core.rb @@ -1,45 +1,39 @@ -require_rspec = if defined?(require_relative) - lambda do |path| - require_relative path - end -else # for 1.8.7 - lambda do |path| - require "rspec/#{path}" - end -end - -require 'set' require 'time' require 'rbconfig' -require_rspec['core/version'] - -require 'rspec/support/caller_filter' -require 'rspec/core/warnings' - -require_rspec['core/flat_map'] -require_rspec['core/filter_manager'] -require_rspec['core/dsl'] -require_rspec['core/notifications'] -require_rspec['core/reporter'] - -require_rspec['core/hooks'] -require_rspec['core/memoized_helpers'] -require_rspec['core/metadata'] -require_rspec['core/pending'] -require_rspec['core/formatters'] -require_rspec['core/ordering'] - -require_rspec['core/world'] -require_rspec['core/configuration'] -require_rspec['core/option_parser'] -require_rspec['core/configuration_options'] -require_rspec['core/command_line'] -require_rspec['core/runner'] -require_rspec['core/example'] -require_rspec['core/shared_example_group/collection'] -require_rspec['core/shared_example_group'] -require_rspec['core/example_group'] +require "rspec/support" +RSpec::Support.require_rspec_support "caller_filter" + +RSpec::Support.define_optimized_require_for_rspec(:core) { |f| require_relative f } + +%w[ + version + warnings + + flat_map + filter_manager + dsl + notifications + reporter + + hooks + memoized_helpers + metadata + pending + formatters + ordering + + world + configuration + option_parser + configuration_options + command_line + runner + example + shared_example_group/collection + shared_example_group + example_group +].each { |name| RSpec::Support.require_rspec_core name } module RSpec autoload :SharedContext, 'rspec/core/shared_context' diff --git a/lib/rspec/core/configuration.rb b/lib/rspec/core/configuration.rb index 8277a8a768..821b062155 100644 --- a/lib/rspec/core/configuration.rb +++ b/lib/rspec/core/configuration.rb @@ -1,7 +1,8 @@ require 'fileutils' -require 'rspec/core/backtrace_formatter' -require 'rspec/core/ruby_project' -require 'rspec/core/formatters/deprecation_formatter' + +RSpec::Support.require_rspec_core "backtrace_formatter" +RSpec::Support.require_rspec_core "ruby_project" +RSpec::Support.require_rspec_core "formatters/deprecation_formatter" module RSpec module Core @@ -422,7 +423,7 @@ def mock_with(framework) "Pass a module or one of #{MOCKING_ADAPTERS.keys.inspect}" end - require "rspec/core/mocking_adapters/#{const_name.to_s.downcase}" + RSpec::Support.require_rspec_core "mocking_adapters/#{const_name.to_s.downcase}" RSpec::Core::MockingAdapters.const_get(const_name) end diff --git a/lib/rspec/core/configuration_options.rb b/lib/rspec/core/configuration_options.rb index 3a567e8088..85504e43b7 100644 --- a/lib/rspec/core/configuration_options.rb +++ b/lib/rspec/core/configuration_options.rb @@ -1,5 +1,6 @@ require 'erb' require 'shellwords' +require 'set' module RSpec module Core diff --git a/lib/rspec/core/drb_command_line.rb b/lib/rspec/core/drb_command_line.rb index 8f390d9276..db4ab648b8 100644 --- a/lib/rspec/core/drb_command_line.rb +++ b/lib/rspec/core/drb_command_line.rb @@ -1,5 +1,5 @@ require 'drb/drb' -require 'rspec/core/drb_options' +RSpec::Support.require_rspec_core "drb_options" module RSpec module Core diff --git a/lib/rspec/core/formatters.rb b/lib/rspec/core/formatters.rb index ef6900e3c5..475ad98a36 100644 --- a/lib/rspec/core/formatters.rb +++ b/lib/rspec/core/formatters.rb @@ -1,4 +1,4 @@ -require 'rspec/core/formatters/legacy_formatter' +RSpec::Support.require_rspec_core 'formatters/legacy_formatter' # ## Built-in Formatters # diff --git a/lib/rspec/core/formatters/base_formatter.rb b/lib/rspec/core/formatters/base_formatter.rb index e4c3683d69..f1932dc678 100644 --- a/lib/rspec/core/formatters/base_formatter.rb +++ b/lib/rspec/core/formatters/base_formatter.rb @@ -1,4 +1,4 @@ -require 'rspec/core/formatters/helpers' +RSpec::Support.require_rspec_core "formatters/helpers" require 'stringio' module RSpec diff --git a/lib/rspec/core/formatters/base_text_formatter.rb b/lib/rspec/core/formatters/base_text_formatter.rb index 398d6b48a7..3b88e5ad3f 100644 --- a/lib/rspec/core/formatters/base_text_formatter.rb +++ b/lib/rspec/core/formatters/base_text_formatter.rb @@ -1,4 +1,4 @@ -require 'rspec/core/formatters/base_formatter' +RSpec::Support.require_rspec_core "formatters/base_formatter" require 'set' module RSpec diff --git a/lib/rspec/core/formatters/deprecation_formatter.rb b/lib/rspec/core/formatters/deprecation_formatter.rb index 4f99bcc5c4..693665bc32 100644 --- a/lib/rspec/core/formatters/deprecation_formatter.rb +++ b/lib/rspec/core/formatters/deprecation_formatter.rb @@ -1,4 +1,4 @@ -require 'rspec/core/formatters/helpers' +RSpec::Support.require_rspec_core "formatters/helpers" require 'set' module RSpec diff --git a/lib/rspec/core/formatters/documentation_formatter.rb b/lib/rspec/core/formatters/documentation_formatter.rb index d5b2f1b70e..3a27a91fa6 100644 --- a/lib/rspec/core/formatters/documentation_formatter.rb +++ b/lib/rspec/core/formatters/documentation_formatter.rb @@ -1,4 +1,4 @@ -require 'rspec/core/formatters/base_text_formatter' +RSpec::Support.require_rspec_core "formatters/base_text_formatter" module RSpec module Core diff --git a/lib/rspec/core/formatters/html_formatter.rb b/lib/rspec/core/formatters/html_formatter.rb index b8092e4e8b..8caed3a030 100644 --- a/lib/rspec/core/formatters/html_formatter.rb +++ b/lib/rspec/core/formatters/html_formatter.rb @@ -1,5 +1,5 @@ -require 'rspec/core/formatters/base_text_formatter' -require 'rspec/core/formatters/html_printer' +RSpec::Support.require_rspec_core "formatters/base_text_formatter" +RSpec::Support.require_rspec_core "formatters/html_printer" module RSpec module Core @@ -134,7 +134,7 @@ def percent_done # could output links to images or other files produced during the specs. # def extra_failure_content(exception) - require 'rspec/core/formatters/snippet_extractor' + RSpec::Support.require_rspec_core "formatters/snippet_extractor" backtrace = exception.backtrace.map {|line| configuration.backtrace_formatter.backtrace_line(line)} backtrace.compact! @snippet_extractor ||= SnippetExtractor.new diff --git a/lib/rspec/core/formatters/json_formatter.rb b/lib/rspec/core/formatters/json_formatter.rb index c862f3d972..8f261054a3 100644 --- a/lib/rspec/core/formatters/json_formatter.rb +++ b/lib/rspec/core/formatters/json_formatter.rb @@ -1,4 +1,4 @@ -require 'rspec/core/formatters/base_formatter' +RSpec::Support.require_rspec_core "formatters/base_formatter" require 'json' module RSpec diff --git a/lib/rspec/core/formatters/legacy_formatter.rb b/lib/rspec/core/formatters/legacy_formatter.rb index 9db6c66a58..b4990ef92d 100644 --- a/lib/rspec/core/formatters/legacy_formatter.rb +++ b/lib/rspec/core/formatters/legacy_formatter.rb @@ -1,4 +1,4 @@ -require 'rspec/core/formatters/helpers' +RSpec::Support.require_rspec_core "formatters/helpers" require 'stringio' module RSpec diff --git a/lib/rspec/core/formatters/progress_formatter.rb b/lib/rspec/core/formatters/progress_formatter.rb index 9d15f403de..fbe938cdeb 100644 --- a/lib/rspec/core/formatters/progress_formatter.rb +++ b/lib/rspec/core/formatters/progress_formatter.rb @@ -1,4 +1,5 @@ -require 'rspec/core/formatters/base_text_formatter' +RSpec::Support.require_rspec_core "formatters/base_text_formatter" + module RSpec module Core module Formatters diff --git a/lib/rspec/core/notifications.rb b/lib/rspec/core/notifications.rb index 9801751804..b2376e6e5d 100644 --- a/lib/rspec/core/notifications.rb +++ b/lib/rspec/core/notifications.rb @@ -1,4 +1,4 @@ -require 'rspec/core/formatters/helpers' +RSpec::Support.require_rspec_core "formatters/helpers" module RSpec::Core module Notifications diff --git a/lib/rspec/core/option_parser.rb b/lib/rspec/core/option_parser.rb index 54dee92133..498a9392c5 100644 --- a/lib/rspec/core/option_parser.rb +++ b/lib/rspec/core/option_parser.rb @@ -92,7 +92,7 @@ def parser(options) end parser.on('--init', 'Initialize your project with RSpec.') do |cmd| - require 'rspec/core/project_initializer' + RSpec::Support.require_rspec_core "project_initializer" ProjectInitializer.new.run exit end diff --git a/lib/rspec/core/ordering.rb b/lib/rspec/core/ordering.rb index 7cc27fa43c..4388bf07ec 100644 --- a/lib/rspec/core/ordering.rb +++ b/lib/rspec/core/ordering.rb @@ -3,7 +3,7 @@ module Core if defined?(::Random) RandomNumberGenerator = ::Random else - require 'rspec/core/backport_random' + RSpec::Support.require_rspec_core "backport_random" RandomNumberGenerator = RSpec::Core::Backports::Random end diff --git a/lib/rspec/core/rake_task.rb b/lib/rspec/core/rake_task.rb index 649923672d..01e7896a26 100644 --- a/lib/rspec/core/rake_task.rb +++ b/lib/rspec/core/rake_task.rb @@ -1,4 +1,6 @@ -require 'rspec/support/warnings' +require 'rspec/support' +RSpec::Support.require_rspec_support "warnings" + require 'rake' require 'rake/tasklib' require 'shellwords' diff --git a/spec/rspec/core/configuration_spec.rb b/spec/rspec/core/configuration_spec.rb index 2eba4de1a3..a148361483 100644 --- a/spec/rspec/core/configuration_spec.rb +++ b/spec/rspec/core/configuration_spec.rb @@ -109,7 +109,7 @@ def absolute_path_to(dir) describe "#mock_framework" do it "defaults to :rspec" do - expect(config).to receive(:require).with('rspec/core/mocking_adapters/rspec') + expect(RSpec::Support).to receive(:require_rspec_core).with('mocking_adapters/rspec') config.mock_framework end end @@ -168,13 +168,13 @@ def absolute_path_to(dir) end it 'uses the named adapter' do - expect(config).to receive(:require).with("rspec/core/mocking_adapters/mocha") + expect(RSpec::Support).to receive(:require_rspec_core).with('mocking_adapters/mocha') stub_const("RSpec::Core::MockingAdapters::Mocha", Module.new) config.mock_with :mocha end it "uses the null adapter when given :nothing" do - expect(config).to receive(:require).with('rspec/core/mocking_adapters/null').and_call_original + expect(RSpec::Support).to receive(:require_rspec_core).with('mocking_adapters/null').and_call_original config.mock_with :nothing end @@ -191,9 +191,13 @@ def absolute_path_to(dir) end context 'when there are already some example groups defined' do + before { allow(RSpec::Support).to receive(:require_rspec_core) } + it 'raises an error since this setting must be applied before any groups are defined' do allow(RSpec.world).to receive(:example_groups).and_return([double.as_null_object]) - stub_const("RSpec::Core::MockingAdapters::Mocha", double(:framework_name => :mocha)) + mocha = stub_const("RSpec::Core::MockingAdapters::Mocha", Module.new) + allow(mocha).to receive_messages(:framework_name => :mocha) + expect { config.mock_with :mocha }.to raise_error(/must be configured before any example groups are defined/) @@ -206,7 +210,9 @@ def absolute_path_to(dir) end it 'does not raise an error if re-setting the same config' do - stub_const("RSpec::Core::MockingAdapters::Mocha", double(:framework_name => :mocha)) + mocha = stub_const("RSpec::Core::MockingAdapters::Mocha", Module.new) + allow(mocha).to receive_messages(:framework_name => :mocha) + groups = [] allow(RSpec.world).to receive_messages(:example_groups => groups) config.mock_with :mocha