> On Apr 11, 2019, at 15:20, Karen Kinnear <[email protected]> wrote:
>
> 2. circularity handling for value type fields - proposed experiment with vm
> detection
> Remi: if VM determines where to “stop” flattening the results will be random
> locations - which will change performance
> Karen: Frederic prototyping in progress -
> - choice of field to flatten is random: based on dynamic loading order
> John: give tools responsibility, so vm doesn’t make the decision, potential
> user model issue
> (ed. note: more discussion to come - including options such as not flattening
> any field involved in circularity/performance cost, tool choice, user model
> choice)
Here’s the results of the exploration:
1 - The JVM could be able to deal with cycles by stopping field flattening.
The class loading and field layout computation have been updated to
support cycles without major issues. CI was not fixed, it currently
enters
an infinite recursive loop, but after a discussion with Tobias, it seems
that
we should be able to handle that properly.
2 - The next question is what to do when a cycle is detected. The solution
implemented in the prototype was to try to flattened as much as possible,
and to refuse to flatten the last field closing the cycle. The problem
with this
strategy is that the layout of data structures depends on the first
class of the cycle
that is loaded. For the end user, this means that performance will
depends
on class loading order, something that the user doesn’t necessarily
controls.
Example with the test program attached to this mail. The argument
controls
execution of different branches which trigger class loading in different
order.
Then, whatever argument has been passed, the same loop is executed
(runs are using the interpreter because of the CI issue, with a JIT, the
differences should be less significant) :
fparain-mac:valhalla fparain$ ./build/macosx-x64-debug/jdk/bin/java
-XX:+EnableValhalla -Xint CycleTest A
Average: 647.0 ops/ms
fparain-mac:valhalla fparain$ ./build/macosx-x64-debug/jdk/bin/java
-XX:+EnableValhalla -Xint CycleTest B
Average: 890.0 ops/ms
fparain-mac:valhalla fparain$ ./build/macosx-x64-debug/jdk/bin/java
-XX:+EnableValhalla -Xint CycleTest C
Average: 642.0 ops/ms
And the explanation of the difference of throughput comes directly from
the difference of layouts:
With argument A:
Class CycleTest$A [@app]:
@ 16 "i" I
@ 24 "b" QCycleTest$B; // flattenable and flattened
@ 24 "j" I
@ 32 "c" QCycleTest$C; // flattenable and flattened
@ 32 "k" I
@ 36 "a" QCycleTest$A; // flattenable not flattened
With argument B:
Class CycleTest$A [@app]:
@ 16 "i" I
@ 20 "b" QCycleTest$B; // flattenable not flattened
With argument C:
Class CycleTest$A [@app]:
@ 16 "i" I
@ 24 "b" QCycleTest$B; // flattenable and flattened
@ 24 "j" I
@ 28 "c" QCycleTest$C; // flattenable not flattened
Dan suggested another strategy to ensure consistent layouts and
performances: whenever a cycle
is detected, non of the field involved in this cycle is flattened. We can
implement this solution too.
The other solutions that have been proposed rely on the user or javac to
prevent the creation of
cycles. These solutions don’t require modification of the JVM, it would keep
its current behavior
which is to throw a ClassCircularityError when it detects a cycle.
Fred