Hi Bernd,

It seems that only bad hash codes (without comparable keys) in JDK8 HM are worse than JDK7 HM.


Since you have already taken time to measure JDK7 vs JDK8 HM, could you try to take the JDK8 source and just replace the internal "comparableClassFor" method with the following implementation:

static final ClassValue<Boolean> selfComparable = new ClassValue<Boolean>() {
        @Override
        protected Boolean computeValue(Class<?> c) {
            Type[] as; ParameterizedType p;
            for (Type t : c.getGenericInterfaces()) {
                if (t instanceof ParameterizedType &&
(p = (ParameterizedType) t).getRawType() == Comparable.class &&
                    (as = p.getActualTypeArguments()).length == 1 &&
                    as[0] == c) // type arg is c
                    return true;
            }
            return false;
        }
    };

    static Class<?> comparableClassFor(Object x) {
        if (x instanceof Comparable) {
            Class<?> c = x.getClass();
            if (c == String.class || selfComparable.get(c)) {
                return c;
            }
        }
        return null;
    }


...and retry your measurements. I just want to see if it has any impact.


Thanks, Peter


On 01/08/2015 05:38 PM, Bernd Eckenfels wrote:
Hello,

I think it was topic before, but I just wanted to point out, that it is
still an topic on the internetz. :)

Motivated by a StackOverflow question regarding HashMap performance
regression in Java 8

http://stackoverflow.com/questions/27759527/using-java-7-hashmap-in-java-8/27760442

I made a JMH test and compared 7 and 8 speed. (the test is not very scientific 
as I dont really know how to squeeze the longrunning loop which alters state 
into the harness, but the results seem to be consitent wth theory and stopwatch 
testing)

https://gist.github.com/ecki/9f69773eb29428a36077

What can be seen is, that with a good distribution of hash keys 8 looks
faster than 7, and with a bad distribution of hash keys Java 7 is
faster (unless you supply a Comparator for the key). (and a good distributed 
hashkey with comparable seems to be a bit slower)

I think the regression is somewhat expected, but I guess its not widely
known.

(I do not use a cached hashcode, but it has a nearly trivial implementation 
just to make it more life like. the tests also compares different initial 
sizes, but they do not have
an measurable effect on the performance, I show only default size below:)

java version "1.7.0_72"
Benchmark (initialSize) Mode Samp Score Error Units
n.e.j.h.HashMapCollision.badDistNoComp 16    avgt 4   10847,318 ± 5596,690 ms/op
n.e.j.h.HashMapCollision.badDistWithComp 16  avgt 4   10761,430 ± 5376,975 ms/op
n.e.j.h.HashMapCollision.goodDistNoComp 16   avgt 4    3613,923 ± 254,823 ms/op
n.e.j.h.HashMapCollision.goodDistWithComp 16 avgt 4    3656,229 ± 274,350 ms/op
java version "1.8.0_25" Benchmark (initialSize) Mode Samp Score Error Units
n.e.j.h.HashMapCollision.badDistNoComp 16    avgt 4    14309,880 ± 1811,709 ms/op 
<-slower
n.e.j.h.HashMapCollision.badDistWithComp 16  avgt 4     8232,037 ± 5974,530 
ms/op
n.e.j.h.HashMapCollision.goodDistNoComp 16   avgt 4     3304,698 ± 116,866 ms/op
n.e.j.h.HashMapCollision.goodDistWithComp 16 avgt 4     3425,762 ± 107,659 ms/op


Greetings
Bernd

Reply via email to