Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RubyConf - Parallel testing with Ractors

RubyConf - Parallel testing with Ractors

Parallelizing tests is an opportune way of reducing the total runtime for a test suite. Rails achieves this by forking multiple separate workers that fetch tests from a queue. In Ruby 3, Ractors introduced new mechanisms for executing code in parallel. Can they be leveraged by a test framework? And how would that compare to current parallelization solutions?

Let’s find the answers to these questions by building a test framework built on Ractors, from scratch. We’ll compare the current solutions for parallelization and what advantages or limitations Ractors bring when used in this context.

Vinicius Stock

October 27, 2021
Tweet

More Decks by Vinicius Stock

Other Decks in Programming

Transcript

  1. Vinicius “Vini” Stock Senior developer @ Shopify Ruby Types team

    Twitter & GitHub: @vinistock https://vinistock.com
  2. Figure out which tests to run Separate tests into groups

    CPU 1 Run test group #1 CPU 2 Run test group #2 CPU 3 Run test group #3 CPU 4 Run test group #4 Execution strategy #1 - Groups Simple Doesn’t guarantee even distribution
  3. CPU 1 CPU 2 Execution strategy #1 Unit test #1

    Unit test #2 Unit test #3 Integration test #1 Unit test #4 Integration test #2 CPU 2 is idle! Unit test #5
  4. Figure out which tests to run Randomize and organize tests

    in a queue Test 1, test 2, test 3, test 4 CPU 1 CPU 2 CPU 3 CPU 4 Execution strategy #2 - Queue
  5. CPU 1 Queue Execution strategy #2 PostTest#test_title PostTest#test_author AuthorTest#test_name PostTest#test_score

    AuthorTest#test_bio CPU 2 PostTest#test_title PostTest#test_author AuthorTest#test_name PostTest#test_score
  6. Figure out which tests to run Separate tests into groups

    CPU 1 Run test group #1 CPU 2 Run test group #2 CPU 3 Run test group #3 CPU 4 Run test group #4 Execution strategy #3 - Work stealing https://en.wikipedia.org/wiki/Work_stealing
  7. CPU 1 CPU 2 Execution strategy #3 Unit test #1

    Unit test #2 Unit test #3 Integration test #1 Unit test #4 Integration test #2 Unit test #5 Reduces communication overhead
  8. Rails Minitest plugin Queue object 
 Test 1, test 2,

    test 3, test 4 PROCESS 1 PROCESS 2 PROCESS 3 PROCESS 4 DRb
  9. Test frameworks - utilities • Define the syntax • Assist

    execution flow • Delegate information • Provide helpers
  10. Test frameworks - utilities & reporting assert(something) Passed continue Failed

    Skip to next item in the queue Save failure info Reporter
  11. Test frameworks - utilities & reporting PostTest :test_author #<PostTest:0x0…> Increment

    total tests setup send(:test_author) teardown Increment successful tests Print success dot
  12. Highlights Can only test Ractor compatible code Can’t make broad

    usage of class variables Can’t make broad usage of meta-programming
  13. Highlights Can test code that spawns more Ractors Can run

    our tests in parallel Doesn’t pay initial cost of forking processes
  14. Seg fault on GC sweep + yield https://bugs.ruby-lang.org/issues/18117 Seg fault

    when freeing classes created inside Ractors https://bugs.ruby-lang.org/issues/18119 Dead lock when using autoload https://bugs.ruby-lang.org/issues/18120 Bug hunt! Seg fault on GC sweep + yield https://bugs.ruby-lang.org/issues/18117