given the interfaces (which are very large and generated out of language definitions):
interface VisitorA {
default void visit(ASTA1 node) {...}
...
default void visit(ASTA2000 node) {...}
}
interface VisitorB extends VisitorA {
default void visit(ASTB1 node) {...}
...
default void visit(ASTB1000 node) {...}
// due to language embedding all visit methods of VisitorA
// must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
@Override
default void visit(ASTA2000 node) {...}
}
interface VisitorC extends VisitorA {
default void visit(ASTC1 node) {...}
...
default void visit(ASTC1000 node) {...}
// due to language embedding all visit methods of VisitorA
// must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
@Override
default void visit(ASTA2000 node) {...}
}
interface VisitorD extends VisitorB, VisitorC {
default void visit(ASTD1 node) {...}
...
default void visit(ASTD1000 node) {...}
// due to language embedding all visit methods of VisitorA,
// VisitorB, and VisitorC must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
@Override
default void visit(ASTA2000 node) {...}
@Override
default void visit(ASTB1 node) {...}
...
@Override
default void visit(ASTB1000 node) {...}
@Override
default void visit(ASTC1 node) {...}
...
@Override
default void visit(ASTC1000 node) {...}
}
Now compiling the interface VisitorA (containing of about 2.000 overloaded methods) needs about 10s. Compiling the interfaces VisitorB and VisitorC needs each about 1.5 min. But when we try to compile the interface VisitorD, the Java 8 compiler needs about 7 minutes!
- Has anybody an idea why it needs so much time to compile VisitorD?
- Is it because of the inheritance of the default methods?
- Or is it because of the diamond constellation, VisitorB as well as VisitorC extend both VisitorA and VisitorD extends VisitorB and VisitorC again?
We already tried around and the following solution helped a little bit:
interface VisitorAPlain {
void visit(ASTA1 node);
...
void visit(ASTA2000 node);
}
interface VisitorA extends VisitorAPlain {
... // has same default methods as VisitorA above
}
interface VisitorBPlain extends VisitorAPlain {
void visit(ASTB1 node);
...
void visit(ASTB1000 node);
}
interface VisitorB extends VisitorBPlain {
... // has same default methods as VisitorB above
}
interface VisitorCPlain extends VisitorAPlain {
void visit(ASTC1 node);
...
void visit(ASTC1000 node);
}
interface VisitorC extends VisitorCPlain {
... // has same default methods as VisitorC above
}
interface VisitorD extends VisitorBPlain, VisitorCPlain {
default void visit(ASTD1 node) {...}
...
default void visit(ASTD1000 node) {...}
// due to language embedding all visit methods of VisitorAPlain,
// VisitorBPlain, and VisitorCPlain must be overwritten
@Override
default void visit(ASTA1 node) {...}
...
default void visit(ASTA2000 node) {...}
@Override
default void visit(ASTB1 node) {...}
...
default void visit(ASTB1000 node) {...}
@Override
default void visit(ASTC1 node) {...}
...
default void visit(ASTC1000 node) {...}
}
And now the compilation time of the visitorD needs only about 2 minutes. But still this is a lot.
- Has anybody an idea how to reduce the compilation time of VisitorD to a few seconds?
- If we remove the two extends relation of VisitorD,
extends VisitorBPlain, VisitorCPlain
, then the compilation time of this interface needs about 15s - even though it has about 5.000 default methods. But we need the that VisitorD is compatible to VisitorB and VisitorC (either by direct extension or the indirect one with the intermediate Plain-interfaces) for casting reasons.
I also read the answers to the similar question: slow JDK8 compilation but there the problem seemed to be the with generic type inference: "There's a severe performance regression in Java 8 when it comes to overload resolution based on generic target typing."
So this is kind of different, if anybody would have a tip or a good explanation why it is so; I would be very thankful.
Thank you, Michael
visitAst1(AST1)
. (This is what most visitors do anyway.) – Eanoreaccept(Visitor v)
method inAST1
delegates tov.visitAst1(this)
. – Eanore