I have been implementing a Smalltalk on the JVM (Rtalk)  which has gone quite well.  But recently
I was told that one of our key benchmarks had suffered a large slowdown,  from a few hundred
mS to seconds.  And strangely it gets slower the more its executed until we reset all of the call sites.

Looking closer I found at least one reproducible cause which leads me to think that there is some
issue with how I do PICs and how Hotspot tries to inline them.

We have a common case where we reset an array of objects by copying one instance var to another.
The Smalltalk class of each value can be one of several so there is some level of polymorphism at
each site.  Interesting for several of these arrays the reset time was 200uS or so but for one it was
1000 mS.  The only difference was that in the fast ones the Smalltalk class types were bunched while
in the slow case they were distributed.  I found that by setting all of the Smalltalk classes to the same
type the time dropped to a few hundred uS. Leading me to think my PIC was the problem.

The problem Smalltalk code looks like this:
   idleValue isNil                  
        ifFalse:[finalValue := idleValue deepCopy]                  
        ifTrue:[finalValue := default].

There are two invoke dynamic sites, isNil and deepCopy.  Removing deepCopy has little effect but
removing the isNil test saves most of the time.  Interesting isNil is a very small method ( returns a
constant of true or false ) so my thought is that it would be logically inlined.  While deepCopy is large.

It looks like, from some fine timing, that each time the Smalltalk class changes there is a large amount
of time added to the call.  Which I would expect if there was a deopt whenever a different GWT triggered.
There are 6 GWTs in this chain ( idleValue can be one of six Smalltalk classes).

Any ideas on how I can avoid this?

Each of my Smalltalk objects is an instance of a single Java class.  The Smalltalk class is determined
by a compare on one of its instance vars.  So looking at the Java class at a callsite it would always
be a constant.

My call site chain looks like
        a mutable site whose target is a fixed set of methodHandles terminated by another mutable site
        whose target is the chain of GWTs.

mlvm-dev mailing list

Reply via email to