-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Run tests in parallel #234
Open
alysbrooks
wants to merge
21
commits into
main
Choose a base branch
from
parallelize
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+446
−67
Open
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
32e8eed
Add data structure foundation.
alysbrooks e0f0300
Work from pairing session with Arne.
alysbrooks f128717
Add semi-functional version (with :parallel) as the flag.
alysbrooks 3382198
Add some debugging code for now.
alysbrooks 6a35e46
Add workarounds for now.
alysbrooks a5d2f7f
Replace workarounds by locking require.
alysbrooks 20e2812
Allow parallelization to happen at any level.
alysbrooks cb09129
Clean up.
alysbrooks 503bfe7
Clean up.
alysbrooks 544a3d3
Add benchmarking.
alysbrooks 141683e
Add warning.
alysbrooks cc983c1
Add commandline flag.
alysbrooks e6382b8
Clean up.
alysbrooks 8e07ed6
Add docs and CHANGELOG entry.
alysbrooks fd5bfe9
Fix dash.
alysbrooks dc52eb1
Tweak wording further.
alysbrooks 0136e65
Add option to filter out by test-suite.
alysbrooks 78f2312
Add thread info.
alysbrooks 356d22c
Very WIP plugin for profiling parallel execution.
alysbrooks fbfd541
Post-rebase fixups
plexus 615ea82
Polish up parallelization: clearer config, docs, vestigial code
plexus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# 11. Parallelization | ||
|
||
Parallelization is an optional Kaocha feature, where it distributes your test | ||
workload across multiple threads, to make better use of multiple CPU cores. | ||
|
||
This is still a relatively new feature, one that has a chance of interfering in | ||
various ways with plugins, custom hooks, or the particulars of test setups that | ||
people have "in the wild". We very much welcome feedback and improvements. | ||
Please be mindful and respectful of the maintainers though and report issues | ||
clearly, preferably with a link to a git repository containing a minimal | ||
reproduction of the issue. | ||
|
||
## Configuration and high-level behavior | ||
|
||
You can enable parallelization either via the `--parallelize` command line flag, | ||
or by setting `:parallelize? true` in your `tests.edn`. This is assuming that | ||
you are using the `#kaocha/v1` reader literal to provide normalization. The | ||
canonical configuration key is `:kaocha/parallelize?`. | ||
|
||
Kaocha looks at your tests as a hierarchy, at the top level there are your test | ||
suites (e.g. unit vs intergration, or clj vs cljs). These contain groups of | ||
tests (their children), e.g. one for each namespace, and these in turn contain | ||
multiple tests, e.g. one for each test var. | ||
|
||
Setting `:parallelize true?` at the top-level configuration, or using the | ||
command line flag, will run any suites you have in parallel, as well making | ||
parallelization the default for any type of testable that has children. So say | ||
for instance you have a suite of type `clojure.test`, then multiple test | ||
namespaces will be run in parallel, and individual test vars within those | ||
namespaces will also be started in parallel. | ||
|
||
Test type implementations need to opt-in to parallelization. For instance, | ||
Clojure is multi-threaded, but ClojureScript (running on a JavaScript runtime) | ||
is not, so thre is little benefit in trying to parallelize ClojureScript tests. | ||
So even with parallelization on, `kaocha.cljs` or `kaocha.cljs2` tests will | ||
still run in series. | ||
|
||
## Fine-grained opting in or out | ||
|
||
Using the command line flag or setting `:parallelize? true` at the top-level of | ||
tests.edn will cause any testable that is parallelizable to be run in parallel. | ||
If you want more fine-grained control you can configure specific test suites to | ||
be parallelized, or set metadata on namespaces to opt in or out of | ||
parallelization. | ||
|
||
```clj | ||
#kaocha/v1 | ||
{:tests [{:id :unit, :parallelize? true}]) | ||
``` | ||
|
||
This will cause all namespaces in the unit test suite to be run in parallel, but | ||
since the default (top-level config) is not set, vars within those namespaces | ||
will not run in parallel. But you can again opt-in at that specific level, | ||
through metadata. | ||
|
||
```clj | ||
(ns ^{:kaocha/parallelize? true} my-test | ||
(:require [clojure.test :as t])) | ||
|
||
... | ||
``` | ||
|
||
Conversely you can opt-out of parallelization on the test suite or test | ||
namespace level by setting `:kaocha/parallelize? false`. | ||
|
||
## Caveats | ||
|
||
When you start running your tests in parallel you will likely notice one or two | ||
things. The first is that your output looks all messed up. Before you might see | ||
something like `[(....)(.......)][(.......)]`, whereas now it looks more like | ||
`[[(..(..).....(..)...]....)]`. This will be even more pronounced if you are for | ||
instance using the documentation reporter. Output from multiple tests gets | ||
interleaved, causing a garbled mess. | ||
|
||
The default dots reporter is probably the most usable reporter right now. | ||
|
||
The second thing you might notice is that you are getting failures where before | ||
you got none. This likely indicates that your tests themselves are not thread | ||
safe. They may for instance be dealing with shared mutable state. | ||
|
||
You will have to examine your code carefully. Starting out with a more piecemeal | ||
opting in might be helpful to narrow things down. | ||
|
||
It is also possible that you encounters failures caused by Kaocha itself. In | ||
that case please report them on our issue tracker. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
|
||
(ns benchmark | ||
(:require [criterium.core :as c]) | ||
(:import [java.util.concurrent Executors ]) | ||
) | ||
|
||
(def thread-pool (Executors/newFixedThreadPool 10)) | ||
|
||
(defn math-direct [] | ||
(+ 1 1)) | ||
|
||
(defn math-future [] | ||
(deref | ||
(future (+ 1 1)))) | ||
|
||
(defn math-thread [] | ||
(let [result (atom nil)] | ||
(doto (Thread. (fn [] (reset! result (+ 1 1)))) | ||
(.start) | ||
(.join)) | ||
@result)) | ||
|
||
(defn math-threadpool [] | ||
(let [result (atom nil)] | ||
(.get (.submit thread-pool (fn [] (reset! result (+ 1 1))) )) | ||
@result)) | ||
|
||
(defn math-threadpool-no-atom [] | ||
(.get (.submit thread-pool (fn [] (+ 1 1)) ))) | ||
|
||
|
||
(c/bench (math-direct) ) | ||
; (out) Evaluation count : 6215391600 in 60 samples of 103589860 calls. | ||
; (out) Execution time mean : 2,015262 ns | ||
; (out) Execution time std-deviation : 0,497743 ns | ||
; (out) Execution time lower quantile : 1,442374 ns ( 2,5%) | ||
; (out) Execution time upper quantile : 3,392990 ns (97,5%) | ||
; (out) Overhead used : 7,915626 ns | ||
; (out) | ||
; (out) Found 5 outliers in 60 samples (8,3333 %) | ||
; (out) low-severe 3 (5,0000 %) | ||
; (out) low-mild 2 (3,3333 %) | ||
; (out) Variance from outliers : 94,6147 % Variance is severely inflated by outliers | ||
|
||
(c/bench (math-future) ) | ||
; (out) Evaluation count : 3735420 in 60 samples of 62257 calls. | ||
; (out) Execution time mean : 16,635809 µs | ||
; (out) Execution time std-deviation : 1,104338 µs | ||
; (out) Execution time lower quantile : 15,397518 µs ( 2,5%) | ||
; (out) Execution time upper quantile : 19,751883 µs (97,5%) | ||
; (out) Overhead used : 7,915626 ns | ||
; (out) | ||
; (out) Found 6 outliers in 60 samples (10,0000 %) | ||
; (out) low-severe 3 (5,0000 %) | ||
; (out) low-mild 3 (5,0000 %) | ||
; (out) Variance from outliers : 50,0892 % Variance is severely inflated by outliers | ||
|
||
(c/bench (math-thread)) | ||
|
||
; (out) Evaluation count : 774420 in 60 samples of 12907 calls. | ||
; (out) Execution time mean : 82,513236 µs | ||
; (out) Execution time std-deviation : 5,706987 µs | ||
; (out) Execution time lower quantile : 75,772237 µs ( 2,5%) | ||
; (out) Execution time upper quantile : 91,971212 µs (97,5%) | ||
; (out) Overhead used : 7,915626 ns | ||
; (out) | ||
; (out) Found 1 outliers in 60 samples (1,6667 %) | ||
; (out) low-severe 1 (1,6667 %) | ||
; (out) Variance from outliers : 51,7849 % Variance is severely inflated by outliers | ||
|
||
(c/bench (math-threadpool)) | ||
; (out) Evaluation count : 3815100 in 60 samples of 63585 calls. | ||
; (out) Execution time mean : 16,910124 µs | ||
; (out) Execution time std-deviation : 2,443261 µs | ||
; (out) Execution time lower quantile : 14,670118 µs ( 2,5%) | ||
; (out) Execution time upper quantile : 23,743868 µs (97,5%) | ||
; (out) Overhead used : 7,915626 ns | ||
; (out) | ||
; (out) Found 3 outliers in 60 samples (5,0000 %) | ||
; (out) low-severe 2 (3,3333 %) | ||
; (out) low-mild 1 (1,6667 %) | ||
; (out) Variance from outliers : 82,4670 % Variance is severely inflated by outliers | ||
|
||
|
||
(c/bench (math-threadpool-no-atom)) | ||
|
||
; (out) Evaluation count : 3794940 in 60 samples of 63249 calls. | ||
; (out) Execution time mean : 16,182655 µs | ||
; (out) Execution time std-deviation : 1,215451 µs | ||
; (out) Execution time lower quantile : 14,729393 µs ( 2,5%) | ||
; (out) Execution time upper quantile : 18,549902 µs (97,5%) | ||
; (out) Overhead used : 7,915626 ns | ||
; (out) | ||
; (out) Found 3 outliers in 60 samples (5,0000 %) | ||
; (out) low-severe 2 (3,3333 %) | ||
; (out) low-mild 1 (1,6667 %) | ||
; (out) Variance from outliers : 56,7625 % Variance is severely inflated by outliers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This comment was marked as outdated.
Sorry, something went wrong.