-
-
Notifications
You must be signed in to change notification settings - Fork 64
Performances degradataion in 1.9.0 #624
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
Comments
@jibidus Thanks for reporting. When you distill an illustrating example you might want to focus on which part is taking longer. I assume it happens during sample generation so typically it would be large collections of objects, some kind of recursion or heavily nested flat mapping. |
Example from @jibidus: https://github.com/jibidus/jqwik-perfs-demo/blob/main/src/test/java/org/example/Test.kt import net.jqwik.api.Arbitraries
import net.jqwik.api.Arbitrary
import net.jqwik.api.Combinators.combine
import net.jqwik.api.ForAll
import net.jqwik.api.Property
import net.jqwik.api.Provide
import net.jqwik.api.constraints.UseType
import net.jqwik.api.domains.Domain
import net.jqwik.api.domains.DomainContext
import net.jqwik.api.domains.DomainContextBase
import net.jqwik.kotlin.api.any
import net.jqwik.kotlin.api.anyForSubtypeOf
import net.jqwik.kotlin.api.anyForType
@Domain(MyDomain::class)
@Domain(DomainContext.Global::class)
class Test {
@Property
fun test(@ForAll model: @UseType Model) {
}
}
class MyDomain : DomainContextBase() {
@Provide
fun model(): Arbitrary<Model> = anyForSubtypeOf<Model>()
// Workaround
// fun model(): Arbitrary<Model> = Arbitraries.oneOf(anyForType<Model1>(), anyForType<Model2>(), anyForType<Model3>())
}
sealed interface Model
data class Model1(val attr1: Int, val attr2: Int, val attr3: Int, val attr4: Int) : Model
data class Model2(val attr1: Int, val attr2: Int, val attr3: Int, val attr4: Int) : Model
data class Model3(val attr1: Int, val attr2: Int, val attr3: Int, val attr4: Int) : Model |
Sorry, I deleted my comment because this does not illustrate this issue (test duration is identical between 1.8.5 and 1.9.0 in this example). It illustrates another performance issue with |
At least it shows that it takes much longer than the workaround. |
Here is a simple example which illustrate the observed behaviour: import net.jqwik.api.Arbitrary
import net.jqwik.api.Combinators
import net.jqwik.api.ForAll
import net.jqwik.api.Property
import net.jqwik.api.Provide
import net.jqwik.api.domains.Domain
import net.jqwik.api.domains.DomainContextBase
import net.jqwik.kotlin.api.any
import net.jqwik.kotlin.api.anyForSubtypeOf
import net.jqwik.kotlin.api.combine
@Domain(MyDomain::class)
@Domain(AnotherDomain::class)
class Test {
@Property
fun test(@ForAll model: Model) {
}
}
class MyDomain : DomainContextBase() {
@Provide
fun model(): Arbitrary<Model> = anyForSubtypeOf<Model>()
@Provide
fun attribute() = combine {
val value by Double.any()
combineAs {
Attr(value)
}
}
}
class AnotherDomain : DomainContextBase() {
@Provide
fun attribute() = combine {
val value by Double.any()
combineAs {
Attr(value)
}
}
}
sealed interface Model
data class Model1(val attr1: Attr) : Model
data class Model2(val attr1: Attr) : Model
data class Attr(val value: Double) This involves 3 elements:
The demo project is available here. So, to summarize, the removal of duplicated arbitrary provider, which is not desired i guess, solves the "issue". So we may probably close this issue. |
It would still be interesting to see, why overridden methods make a difference from 1.8.5 to 1.9.0. I will have a look at it, but I cannot promise to do it this week. |
Thanks |
I spent a couple of hours trying to trace the differences in code execution from 1.8.5 to 1.9.0. The two things that have changed are:
The thing that I don't understand at all is that in version >= 1.9.0 the code with two Cutting a long story short: I'm out of ideas - or maybe just dumb. |
One possible next step could be to get rid of the Kotlin part in the example and see if it has anything to do with Kotlin. |
@jlink , have you profiled the execution? I wonder if the profiler would show the key resource consumption, so we could compare it between the releases |
Using @Provide
fun model(): Arbitrary<Model> = Arbitraries.oneOf<Model>(
anyForType<Model1>(),
anyForType<Model2>()
) speeds the code up tremendously. I conclude that the issue is somehow related to Maybe there's a way to get rid of recursion there? Or simplify it in a different way? |
Actually no. Wondering why I haven't. Sadly, I have to let it go for today :-( |
I wrote "same" test in Java : @Domain(Test.MyDomain.class)
@Domain(Test.AnotherDomain.class)
public class Test {
@Property
void test(@ForAll Model model) {
}
static class MyDomain extends DomainContextBase {
@Provide
Arbitrary<Model> model() {
return Arbitraries.oneOf(Arbitraries.forType(Model1.class).enableRecursion(), Arbitraries.forType(Model2.class).enableRecursion());
}
@Provide
Arbitrary<Attr> attribute() {
return Arbitraries.doubles().map(Attr::new);
}
}
static class AnotherDomain extends DomainContextBase {
@Provide
Arbitrary<Attr> attribute() {
return Arbitraries.doubles().map(Attr::new);
}
}
interface Model { }
static class Model1 implements Model {
public Model1(Attr attr1) {
this.attr1 = attr1;
}
private Attr attr1;
}
static class Model2 implements Model {
public Model2(Attr attr1) {
this.attr1 = attr1;
}
private Attr attr1;
}
static class Attr {
private Double value;
public Attr(Double value) {
this.value = value;
}
}
} I did not observed any difference with this test between 1.9.0 and 1.8.5. But this test uses
When, in kotlin test, I replace |
The percentage are aggregated time I assume. What about number of calls? If they are similar in both cases then something strange is going on. In |
In any case, it does not sound right to have a lot of Memoize....computeIfAbsent...put call call stacks. |
Hi @jlink,
I noticed a performance degradation since jqwik 1.9.0 in some of my tests.
I have many tests which heavily use Domain feature, which duration have increased by a factor 5. For example, here are durations for a single test:
I will try to provide a project to illustrate this issue.
The text was updated successfully, but these errors were encountered: