2009/5/7 Egor Pasko <egor.pasko@gmail.com>:
> On the 0x5AA day of Apache Harmony Ian Rogers wrote:
>> 2009/5/6 Egor Pasko <egor.pasko@gmail.com>:
>>>> Thanks Egor :) I don't know if 3 dependent integer operations will
>>>> run faster than two compare and branches as the branches may be
>>>> speculated over. Unfortunately for Jikes RVM we frequently sort arrays
>>>> containing just 0.0 and 1.0 meaning the performance of 0.0 compares
>>>> hurts us.
>>>
>>> Ian, do you really need zeroes in the right order? I'd be really
>>> surprized if you do :) If there are really a lot of +0.0s .. isn't it
>>> faster to count the number of zeroes prior to sorting?
>>
>> Agreed, I'm being lazy in not writing our own sort :)
>>
>>>> Other issues if we're wringing performance:
>>>>
>>>>  could Float.equals be improved in a similar manner to
>>>> Float.compareTo in particular avoiding using floatToIntBits and its
>>>> inherent NaN tests,ie:
>>>>
>>>> public boolean equals(Object object) {
>>>> /* removed as this case seems generally unlikely and is
>>>> covered by the case below
>>>> if (object == this) {
>>>> return true;
>>>> } else */
>
> By the way, I am not eager to disable this (speculative)
> optimization. Can you prove that your new version behaves better on
> common benchmarks?
Sorry no, I was just imagining something like a HashSet containing
100 boxed floats, the chance that the two identities will be the same
is very small  say 1 in 100 if we're searching an element already in
the HashSet, lower if not. I'm not aware of a common benchmark where
this is a performance issue anyway.
>>>> if (object instanceof Float) {
>>>> float otherValue = ((Float) object).value;
>>>> return (floatToRawIntBits(value) ==
>>>> floatToRawIntBits(otherValue)) 
>>>> (isNaN(value) && isNaN(otherValue));
>>>> } else {
>>>> return false;
>>>> }
>>>> }
>>>
>>> is compareTo not suitable here because of the same reasons as in
>>> example below? Or am I missing something?
>>
>> The current equals code doesn't use compareTo and the < and > cases
>> aren't that interesting, the code above is really just putting the
>> same optimizations discussed for compareTo into place for equals.
>
> OK, cool.
>
> not sure I understand the reason to change floatToIntBits() to
> floatToRawIntBits() in the above and comparing with NaN
> explicitly. floatToIntBits() replaes the isNaN() checking at a low
> cost. Most of the time is eaten in JNI transition, I believe.
So we removed the JNI transition and just use an intrinsic operation
in the case of the raw bits. Our operation for non raw bits is:
static int floatToIntBits(float value) {
if (isNaN(value)) return Float.NaN;
else return floatToRawIntBits(value);
}
The floatToRawIntBits of a value in an object on x86 ends up compiling
down to an integer load (move) from memory  or if this value is
compared it can just be a memory operand to a compare instruction (we
use a BURS based instruction selector). The isNaN requires a floating
point comparison, so in the current code we do two isNaN floating
point comparisons prior to the fast raw bit comparison  my change
just moves the isNaN tests to after the raw bit comparison has failed
as I assume NaN is unlikely.
Regards,
Ian
>>>>  is it worth specializing the code in Arrays.lessThan to something
>>>> like (I don't think Jikes RVM can inline compareTo and achieve an
>>>> equivalent transformation and it saves quite a number of compares):
>>>>
>>>> private static boolean lessThan(float float1, float float2) {
>>>> // Nonzero, nonNaN checking.
>>>> if (float2 > float1) {
>>>> return true;
>>>> }
>>>> if (float1 >= float2 && 0.0f != float1) {
>>>> return false;
>>>> }
>>>> // NaNs are equal to other NaNs and larger than any other float
>>>> if (isNaN(float1)) {
>>>> return false;
>>>> } else if (isNaN(float2)) {
>>>> return true;
>>>> }
>>>> // Deal with +0.0 and 0.0
>>>> int f1 = floatToRawIntBits(float1);
>>>> int f2 = floatToRawIntBits(float2);
>>>> return f1 < f2;
>>>> }
>>>
>>> good idea, I'll do that if nobody objects :)
>>
>> Cheers,
>> Ian
>>
>
> 
> Egor Pasko
>
>
