rspec-gc-control 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ ### dev
2
+ [full changelog](http://github.com/MrJoy/rspec-gc-control/compare/v1.0.0...master)
3
+
4
+ Changes
5
+
6
+ * Forgot to update changelog before tagging release.
7
+
8
+
9
+ ### v1.0.0
10
+ [full changelog](http://github.com/MrJoy/rspec-gc-control/compare/1d2bd61...v1.0.0)
11
+
12
+ Initial Version
13
+
14
+ * Add support for controlling how often GC runs on RSpec 2.11.1.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2012 Jon Frisby
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # rspec-gc-control
2
+
3
+ ## Summary
4
+
5
+ This gem extends RSpec to allow you to control how often GC cycles happen
6
+ in order to trade increased memory usage for faster test runs. It's an
7
+ encapsulated and reusable version of the code shown in this article:
8
+
9
+ <http://www.rubyinside.com/careful-cutting-to-get-faster-rspec-runs-with-rails-5207.html>
10
+
11
+
12
+ ## Requirements
13
+
14
+ For this to work, you need a Ruby that supports explicit control over the
15
+ garbage collector, and RSpec 2.11.1 or higher.
16
+
17
+ Supported Rubies include MRI 1.9.2 and 1.9.3, and most likely Rubinius.
18
+
19
+ Unsupported Rubies are:
20
+
21
+ * MRI 1.8.x: No support for `GC.count`.
22
+ * JRuby: `GC.enable` / `GC.disable` are no-ops.
23
+
24
+ On unsupported platforms, attempting to enable explicit GC control via this
25
+ plugin will produce a warning and have no other effect.
26
+
27
+
28
+ ## Installation and Usage
29
+
30
+ Install the gem:
31
+
32
+ ```ruby
33
+ gem install rspec-gc-control
34
+ ```
35
+
36
+ Or if you're using bundler, add this line to your `Gemfile` and run
37
+ `bundle install`:
38
+
39
+ ```ruby
40
+ gem 'rspec-gc-control'
41
+ ```
42
+
43
+ Once you have the gem installed, edit your `spec_helper.rb` file to set
44
+ `gc_every_n_examples` to an appropriate value. You may want to play with this
45
+ value while watching memory consumption for the process to get a feeling for
46
+ how significant a tradeoff you're making in terms of increased memory usage.
47
+
48
+ ```ruby
49
+ RSpec.configure do |c|
50
+ c.gc_every_n_examples = 10
51
+ end
52
+ ```
53
+
54
+ You'll know it's working if you see output like the following at the end of
55
+ your test run:
56
+
57
+ ```
58
+ Finished in 6.45 seconds (including 7 forced GC cycle(s), totalling 0.67116 seconds)
59
+ 71 examples, 0 failures, 1 pending
60
+ ```
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.expand_path("..", __FILE__))
2
+
3
+ require 'rspec-gc-control/configuration'
4
+ require 'rspec-gc-control/example'
5
+ require 'rspec-gc-control/base_text_formatter'
6
+
@@ -0,0 +1,31 @@
1
+ require 'rspec/core/formatters/base_formatter'
2
+
3
+ module RSpec
4
+ module Core
5
+ module Formatters
6
+
7
+ class BaseTextFormatter < BaseFormatter
8
+
9
+ # Overridden version of this method, to include output about forced GC
10
+ # count and duration, if explicit GC control is enabled.
11
+ def dump_summary(duration, example_count, failure_count, pending_count)
12
+ super(duration, example_count, failure_count, pending_count)
13
+ # Don't print out profiled info if there are failures, it just clutters the output
14
+ dump_profile if profile_examples? && failure_count == 0
15
+ output.print "\nFinished in #{format_duration(duration)}"
16
+
17
+ gc_times = examples.map { |ex| ex.execution_result[:gc_time] }.select { |t| !t.nil? && (t > 0) }
18
+ if(gc_times.count > 0)
19
+ gc_count = gc_times.count
20
+ gc_time = gc_times.reduce(:+)
21
+ output.print " (including #{gc_count} forced GC cycle(s), totalling #{format_duration(gc_time)})"
22
+ end
23
+ output.print "\n"
24
+ output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
25
+ dump_commands_to_rerun_failed_examples
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,62 @@
1
+ require 'rspec/core/configuration'
2
+
3
+ module RSpec
4
+ module Core
5
+ # Extensions to RSpec::Core::Configuration to allow configuration of
6
+ # desired GC behavior.
7
+ class Configuration
8
+ # @private
9
+ define_reader :gc_every_n_examples
10
+
11
+ # @private
12
+ alias_method :initialize_without_gc, :initialize
13
+
14
+ # Overridden constructor to initialize `gc_every_n_examples` to 0.
15
+ # This disables the explicit GC control.
16
+ def initialize
17
+ initialize_without_gc
18
+ @gc_every_n_examples = 0
19
+ end
20
+
21
+ # @private
22
+ def gc_if_needed
23
+ gc_time = 0
24
+ if(@gc_every_n_examples > 0)
25
+ @test_counter = -1 if(!defined?(@test_counter))
26
+ @test_counter += 1
27
+ if(@test_counter >= (@gc_every_n_examples - 1))
28
+ t_before = Time.now
29
+ GC.enable
30
+ GC.start
31
+ GC.disable
32
+ gc_time = Time.now - t_before
33
+
34
+ @test_counter = 0
35
+ end
36
+ end
37
+ return gc_time
38
+ end
39
+
40
+ # If set to a value above 0, turns automatic GC off and runs it only
41
+ # every N tests, which can result in higher peak memory usage but lower
42
+ # total execution time.
43
+ def gc_every_n_examples=(n)
44
+ if(defined?(JRuby))
45
+ warn "Ignoring gc_every_n_examples because JRuby doesn't support GC control."
46
+ return
47
+ end
48
+ if(!GC.respond_to?(:count))
49
+ warn "Ignoring gc_every_n_examples because this Ruby implementation doesn't implement GC.count."
50
+ return
51
+ end
52
+ @gc_every_n_examples = n
53
+ if(@gc_every_n_examples > 0)
54
+ GC.disable
55
+ else
56
+ GC.enable
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,26 @@
1
+ require 'rspec/core/example'
2
+
3
+ module RSpec
4
+ module Core
5
+ # Extensions to RSpec::Core::Example to perform explicit GC and capture
6
+ # GC execution time.
7
+ class Example
8
+ private
9
+
10
+ undef :record_finished
11
+ def record_finished(status, results={})
12
+ finished_at = Time.now
13
+ record results.merge(:status => status, :finished_at => finished_at, :run_time => (finished_at - (execution_result[:started_at] + (execution_result[:gc_time] || 0))))
14
+ end
15
+
16
+ alias_method :run_after_each_without_gc, :run_after_each
17
+
18
+ def run_after_each
19
+ run_after_each_without_gc
20
+ ensure
21
+ execution_result[:gc_time] = RSpec.configuration.gc_if_needed
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,47 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "rspec-gc-control"
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jon Frisby"]
12
+ s.date = "2012-08-12"
13
+ s.description = "Explicit control over garbage collection behavior for RSpec."
14
+ s.email = "jfrisby@mrjoy.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ "CHANGELOG.md",
21
+ "LICENSE",
22
+ "README.md",
23
+ "lib/rspec-gc-control.rb",
24
+ "lib/rspec-gc-control/base_text_formatter.rb",
25
+ "lib/rspec-gc-control/configuration.rb",
26
+ "lib/rspec-gc-control/example.rb",
27
+ "rspec-gc-control.gemspec"
28
+ ]
29
+ s.homepage = "http://MrJoy.com"
30
+ s.licenses = ["MIT"]
31
+ s.require_paths = ["lib"]
32
+ s.rubygems_version = "1.8.24"
33
+ s.summary = "Explicit control over garbage collection behavior for RSpec."
34
+
35
+ if s.respond_to? :specification_version then
36
+ s.specification_version = 3
37
+
38
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
39
+ s.add_runtime_dependency(%q<rspec-core>, [">= 2.11.1"])
40
+ else
41
+ s.add_dependency(%q<rspec-core>, [">= 2.11.1"])
42
+ end
43
+ else
44
+ s.add_dependency(%q<rspec-core>, [">= 2.11.1"])
45
+ end
46
+ end
47
+
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-gc-control
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jon Frisby
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec-core
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.11.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.11.1
30
+ description: Explicit control over garbage collection behavior for RSpec.
31
+ email: jfrisby@mrjoy.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files:
35
+ - LICENSE
36
+ - README.md
37
+ files:
38
+ - CHANGELOG.md
39
+ - LICENSE
40
+ - README.md
41
+ - lib/rspec-gc-control.rb
42
+ - lib/rspec-gc-control/base_text_formatter.rb
43
+ - lib/rspec-gc-control/configuration.rb
44
+ - lib/rspec-gc-control/example.rb
45
+ - rspec-gc-control.gemspec
46
+ homepage: http://MrJoy.com
47
+ licenses:
48
+ - MIT
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ segments:
60
+ - 0
61
+ hash: -2268877769317612634
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 1.8.24
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Explicit control over garbage collection behavior for RSpec.
74
+ test_files: []