Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[EXPERIMENTAL] run actionpack tests in parallel

only on forking systems though.  Feel free to revert this if it causes
problems.
  • Loading branch information...
commit c64bff2c87ebf363703c63ecd4a96d56a1a78364 1 parent 932386b
@tenderlove tenderlove authored
Showing with 57 additions and 0 deletions.
  1. +57 −0 actionpack/test/abstract_unit.rb
View
57 actionpack/test/abstract_unit.rb
@@ -15,6 +15,10 @@
Encoding.default_external = "UTF-8"
end
+require 'drb'
+require 'drb/unix'
+require 'tempfile'
+
require 'active_support/testing/autorun'
require 'abstract_controller'
require 'action_controller'
@@ -105,6 +109,7 @@ def before_setup
module ActiveSupport
class TestCase
include ActionDispatch::DrawOnce
+ parallelize_me!
end
end
@@ -432,3 +437,55 @@ def rubinius_skip(message = '')
def jruby_skip(message = '')
skip message if defined?(JRUBY_VERSION)
end
+
+class ForkingExecutor
+ class Server
+ include DRb::DRbUndumped
+
+ def initialize
+ @queue = Queue.new
+ end
+
+ def record reporter, result
+ reporter.synchronize { reporter.record result }
+ end
+
+ def << o; @queue << o; end
+ def pop; @queue.pop; end

@tenderlove is there a reason why you prefer these as one-liners over delegate :<<, :pop, to: :@queue (or that, but with private attr_reader :queue?

@tenderlove Owner

delegate adds an extra method call and forces a dependency on AS. These one-liners get the job done without extra dependencies, overhead, or complexity. If the class starts delegating many methods to queue, then we can think about refactoring to use "delegate". I don't think it makes sense for 2 methods though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ end
+
+ def initialize size
+ @size = size
+ @queue = Server.new
+ file = File.join Dir.tmpdir, Dir::Tmpname.make_tmpname('tests', 'fd')
+ @url = "drbunix://#{file}"
+ @pool = nil
+ DRb.start_service @url, @queue
+ end
+
+ def << work; @queue << work; end
+
+ def shutdown
+ pool = @size.times.map {
+ fork {
+ DRb.stop_service
+ DRb.start_service
+ queue = DRbObject.new_with_uri @url
+ while job = queue.pop
+ klass = job[0]
+ method = job[1]
+ reporter = job[2]
+ result = Minitest.run_one_method klass, method
+ queue.record reporter, result
+ end
+ }
+ }
+ @size.times { @queue << nil }
+ pool.each { |pid| Process.waitpid pid }
+ end
+end
+
+if ActiveSupport::Testing::Isolation.forking_env?
+ # Use N processes (N defaults to 4)
+ Minitest.parallel_executor = ForkingExecutor.new((ENV['N'] || 4).to_i)
+end

1 comment on commit c64bff2

@agis-

This introduced rails/rails-dev-box#76

Please sign in to comment.
Something went wrong with that request. Please try again.