spekframework / spek

A specification framework for Kotlin
Other
2.23k stars 179 forks source link

Remove verbose on cg scan and don't use MonoClock in jvm #907

Closed raniejade closed 4 years ago

raniejade commented 4 years ago

//cc @arturbosch

arturbosch commented 4 years ago

@raniejade I will take further look later today.

First results are:

2020-08-01-122948_1435x971_scrot

the rules modules might do heavy work in discovery because of setting up kotlin environments, but the reports and metrics modules for example are so plain simple.

https://scans.gradle.com/s/y6vrsokp6bomg/tests

arturbosch commented 4 years ago

@raniejade if I read this correctly, the classpath scanning is using now one thread by default? Edit: -> no it needs the property.

I've done some testings and the results are the same as the last PR. disableJarScanning decreased it to 2s spek vs 1s jupiter.

I have started using Gradle test fixtures in https://github.com/detekt/detekt/pull/2921. Removing the detekt-test dependency from the detekt-report-txt module lets the tests start instantly. I suspect scanning the whole classpath with the kotlin compiler in it (40mb) is the blocker here.

Edit: also in https://github.com/detekt/detekt/pull/2921 I've found out that reducing the max workers help, so there might still be some thread starving involved. Edit2: @raniejade can you give me hint how I can build a local version of spek for Kotlin 1.3.72 to test some changes? I'm not sure how the versioning works and I get a version only compatible with 1.4.

Edit3: spek seems to be fast in discovery when starting from a single thread aka IntelliJ test. It is kotlinc and mockk being slow in discovery. Which sums up for every module. However I see like 5 coroutine worker threads per test module ... which might lead to thread starving ...

2020-08-01-214027_1467x250_scrot

Edit4: Junit5 Jupiter runs it tests sequential by default, is there a way to do this the same with spek? https://junit.org/junit5/docs/current/user-guide/#writing-tests-parallel-execution

raniejade commented 4 years ago

@arturbosch thanks for looking into this! (I just woke up - sorry for the typos in adv :joy:)

if I read this correctly, the classpath scanning is using now one thread by default? Edit: -> no it needs the property.

Classgraph itself is concurrent by default and spek has been using the default config for a while now. So I didn't change that behaviour, if you want to use a single thread please set spek2.jvm.cg.scan.concurrency to 1.

Removing the detekt-test dependency from the detekt-report-txt module lets the tests start instantly. I suspect scanning the whole classpath with the kotlin compiler in it (40mb) is the blocker here. That's interesting, are you using embedable one? I'll try adding that dependency in one of our test modules.

Edit2: @raniejade can you give me hint how I can build a local version of spek for Kotlin 1.3.72 to test some changes? I'm not sure how the versioning works and I get a version only compatible with 1.4.

Use 2.0.x branch - I had to work with separate branches for the Kotlin 1.4 line due to the compiler plugin changes. See in the for building instructions.

Edit3: spek seems to be fast in discovery when starting from a single thread aka IntelliJ test. It is kotlinc and mockk being slow in discovery. Which sums up for every module. However I see like 5 coroutine worker threads per test module ... which might lead to thread starving

Discovery was never concurrent, the recent PRs just added an option for it to be concurrent but still sequential by default.

Edit4: Junit5 Jupiter runs it tests sequential by default, is there a way to do this the same with spek? junit.org/junit5/docs/current/user-guide/#writing-tests-parallel-execution

Unfortunately no, If you are able to build the 2.0.x branch you can change the following lines:

[1] https://github.com/spekframework/spek/blob/2.0.x/spek-runtime/src/commonMain/kotlin/org/spekframework/spek2/runtime/Executor.kt#L51

[2] https://github.com/spekframework/spek/blob/2.0.x/spek-runtime/src/commonMain/kotlin/org/spekframework/spek2/runtime/Executor.kt#L70

Change it from withContext(Dispatchers.DEFAULT) to something like with(true) (just to avoid a massive change).

For building, just make sure you are in the 2.0.x branch then just run ./gradlew publishToMavenLocal to publish the artifacts locally.

arturbosch commented 4 years ago

Using the Gradle wrapper helped. There was one compilation error using 6.6-rc3:

2020-08-02-090802_1919x555_scrot

Getting rid of coroutines just helped 1-2s like you mentioned. So our problem is too many kotlinc usages in too many modules in too many threads :/.

Big thank you for your time and profiling work!