Permalink
Browse files

Provide an option to use all processors.

This is useful for larger projects. Fixes #28.
  • Loading branch information...
xaviershay committed Aug 27, 2012
1 parent c0f2e45 commit 70a540c058b360e50b646aab054456d8716e9118
Showing with 54 additions and 4 deletions.
  1. +3 −1 Gemfile.lock
  2. +1 −0 cane.gemspec
  3. +20 −0 lib/cane.rb
  4. +5 −1 lib/cane/abc_check.rb
  5. +4 −0 lib/cane/cli/parser.rb
  6. +5 −1 lib/cane/doc_check.rb
  7. +5 −1 lib/cane/style_check.rb
  8. +6 −0 spec/cane_spec.rb
  9. +5 −0 spec/parser_spec.rb
View
@@ -1,13 +1,15 @@
PATH
remote: .
specs:
- cane (2.0.0)
+ cane (2.1.0)
+ parallel
GEM
remote: http://rubygems.org/
specs:
diff-lcs (1.1.3)
multi_json (1.3.2)
+ parallel (0.5.18)
rake (0.9.2.2)
rspec (2.11.0)
rspec-core (~> 2.11.0)
View
@@ -27,6 +27,7 @@ Gem::Specification.new do |gem|
gem.executables << "cane"
gem.version = Cane::VERSION
gem.has_rdoc = false
+ gem.add_dependency 'parallel'
gem.add_development_dependency 'rspec', '~> 2.0'
gem.add_development_dependency 'rake'
gem.add_development_dependency 'simplecov'
View
@@ -1,3 +1,5 @@
+require 'parallel'
+
require 'cane/violation_formatter'
module Cane
@@ -6,6 +8,24 @@ def run(*args)
end
module_function :run
+ def task_runner(opts)
+ if opts[:parallel]
+ Parallel
+ else
+ SimpleTaskRunner
+ end
+ end
+ module_function :task_runner
+
+ # Mirrors the Parallel gem's interface but does not provide any parralleism.
+ # This is faster for smaller tasks since it doesn't incur any overhead for
+ # creating new processes and communicating between them.
+ class SimpleTaskRunner
+ def self.map(enumerable, &block)
+ enumerable.map(&block)
+ end
+ end
+
# Orchestrates the running of checks per the provided configuration, and
# hands the result to a formatter for display. This is the core of the
# application, but for the actual entry point see `Cane::CLI`.
View
@@ -35,7 +35,7 @@ def self.options
def violations
return [] if opts[:no_abc] == false
- order file_names.map {|file_name|
+ order worker.map(file_names) {|file_name|
find_violations(file_name)
}.flatten
end
@@ -192,5 +192,9 @@ def max_allowed_complexity
def exclusions
opts.fetch(:abc_exclude, []).flatten.to_set
end
+
+ def worker
+ Cane.task_runner(opts)
+ end
end
end
View
@@ -106,6 +106,10 @@ def add_cane_options
add_option %w(--max-violations VALUE),
"Max allowed violations", default: 0, cast: :to_i
+ add_option %w(--parallel),
+ "Use all processors. Slower on small projects, faster on large.",
+ cast: ->(x) { x }
+
parser.separator ""
end
View
@@ -24,7 +24,7 @@ def self.options
def violations
return [] if opts[:no_doc]
- file_names.map {|file_name|
+ worker.map(file_names) {|file_name|
find_violations(file_name)
}.flatten
end
@@ -60,6 +60,10 @@ def comment?(line)
def extract_class_name(line)
line.match(/class ([^\s;]+)/)[1]
end
+
+ def worker
+ Cane.task_runner(opts)
+ end
end
end
View
@@ -34,7 +34,7 @@ def self.options
def violations
return [] if opts[:no_style]
- file_list.map do |file_path|
+ worker.map(file_list) do |file_path|
map_lines(file_path) do |line, line_number|
violations_for_line(line.chomp).map {|message| {
file: file_path,
@@ -77,6 +77,10 @@ def exclusions
def excluded?(file)
exclusions.include?(file)
end
+
+ def worker
+ Cane.task_runner(opts)
+ end
end
end
View
@@ -62,6 +62,12 @@ def violations
exitstatus.should == 0
end
+ it 'can run tasks in parallel' do
+ # This spec isn't great, but there is no good way to actually observe that
+ # tasks run in parallel and we want to verify the conditional is correct.
+ Cane.task_runner(parallel: true).should == Parallel
+ end
+
after do
if Object.const_defined?(class_name)
Object.send(:remove_const, class_name)
View
@@ -86,4 +86,9 @@ def run(cli_args)
result[:abc_glob].should == 'myfile'
result[:style_glob].should == 'myotherfile'
end
+
+ it 'allows parallel option' do
+ _, result = run("--parallel")
+ result[:parallel].should be
+ end
end

0 comments on commit 70a540c

Please sign in to comment.