performance degeneration from jdk7u2 to jdk7u6?

Rémi Forax forax at univ-mlv.fr
Thu May 24 04:43:45 PDT 2012


On 05/24/2012 10:38 AM, Jochen Theodorou wrote:
> Am 23.05.2012 23:33, schrieb Rémi Forax:
>> On 05/23/2012 07:50 PM, Jochen Theodorou wrote:
>>> no one helping me on the assembly analysis?
>> Wow, you have generated the biggest fib function I have ever seen.
>>
>> About the bytecode you generate, as you said you have to remove
>> $getCallSiteArray() because it seems it does some side effects
>> so the JIT is not able to remove it.
> the first time an array is generated, later nothing happens anymore...
> but yes, this has to go.
[...]
> the method signature is (I)I, it is called with Object in the body,
> because I cannot ensure that x-1 and x-2 will return an int. Since I
> cannot know for sure that fib(I)I is called, the result of the recursive
> fib call is seen as Object. All I know for sure is that the result of
> "fib(x-1)+fib(x-2)" will be converted to an int later and will cause an
> exception if the conversion is not possible. But that is the result of
> the plus, thus you don't exactly need a compatible return type for fib.
> In for example:
>
> int fib(int x) {
>     if (x<2) return 1
>     this.metaClass.fib = {int i ->  i==1?"Forax":"Remi "}
>     String.metaClass.plus = {String b ->  delegate.length()+b.length()}
>     return fib(x-1)+fib(x-2)
> }
> assert fib(3)== 10
>
> I replace fib inside fib with, well it returns a String, but signature
> wise I replace it with a method returning Object. String is not
> compatible with int. And it does not lead to an exception because I also
> replace String#plus with a version that simply returns the added length
> of both Strings. So fib(3) will call fib(2) and fib(1), which has the
> results "Remi " and "Forax". Then I call plus on those results, leading
> to String#plus, which returns the added lengths, which is 10 and
> compatible with int.

yes, you're right, I've forgotten that you can change two methods
at the same time.

>
>> Also, you should never use methods like
>> |DefaultTypeTransformation.intUnbox|
>> because you know that the return type is an int, you should
>> back-propagate it and the return type of plus should be (Object;Object)I
> in the original example that is true, yes. That may allow to skip at
> intUnbox call... but only if I later select a plus method that returns
> int or Integer. In a different thread I already asked for requirements
> in that direction and that I get very differing results depending on
> what signatures I use. No I have at lest the hint, that returning int or
> Integer might be a good idea.

if invokedynamic knows more, you can provide a path with
less boxing so it's usually better.

>
>> Now, the generated code, because of getCallSiteArray(),
>> your real code starts at line 168 and here you start
>> to box the two ints to two Integers to be able to call
>> NumberMath.subtract(Number,Number) which call
>> IntegerMath.substractImpl that unbox them.
>> The VM is not able to remove calls to box / unbox for j.l.Integer.
> I see... unfortunate.
>
>> You should generate a must simpler path here.
>> You should never call a class like g.r.typehandling.*Math because
>> all of these methods takes Numbers as parameters.
>> You should create one simple class, with methods like this:
>>      static int add(int left, int right) {
>>        return left + right;
>>      }
>> because it doesn't force you to do the boxing.
>> So you will do the boxing only if it's necessary, i.e. only
>> when the parameter is Object.
>> And to now which method you have to call, instead of
>> relying on getMath() you should use guardWithTest and
>> test only parameters that are Object.
> Object is pretty often the case. Well if I count boxing and unboxing for
> (a+b)+(c+d), then now I have to box a to d, unbox for the add, box the
> result, no boxing for the outer plus call, but two unboxing and a boxing
> for the result and... if the method returns int, a final unboxing. That
> makes 7 boxing and 7 unboxing.
>
> If I use your add(II)I and backpropagate the return type, then I have
> one boxing each for the inner pluses, two unboxing for the outer plus.
> Totals to 2 boxing, 2 unboxing. Sounds better... even without
> backpropagating the call. I will try that out.

:)

>
> bye Jochen
>

cheers,
Rémi



More information about the mlvm-dev mailing list