JDK-8210280 - Unnecessary reallocation when invoking HashMap.putAll()

Michal Vala mvala at redhat.com
Tue Dec 11 19:05:33 UTC 2018


Hi,

I've been looking into this bug in HashMap where resize() is called multiple 
times when putting whole map into another.

I come up with following patch: 
http://cr.openjdk.java.net/~mvala/jdk/jdk/JDK-8210280/webrev.00/

I've tried to do it as little invasive as possible. New resize(int) method is 
called just from putMapEntries for now. Notice that method is called with size 
of the new map. I was experimenting with calling it with 'size()+s', but this 
leads to unwanted space allocation when inserted map rewrites a lot of existing 
keys.

I've benchmarked this with adding 10millions elements into existing map and it 
gets ~50% improvement:

unpatched
Benchmark                Mode  Cnt  Score   Error  Units
MyBenchmark.testMethod  thrpt   10  1.248 ± 0.058  ops/s

patched
Benchmark                Mode  Cnt  Score   Error  Units
MyBenchmark.testMethod  thrpt   10  1.872 ± 0.109  ops/s

public class MyBenchmark {
     static Map<Integer, Integer> mapTocopy = IntStream.range(1, 
10_000_000).boxed().collect(Collectors.toMap(k -> k,
             k -> k));

     @Benchmark
     public int testMethod() {
         var map = new HashMap<Integer, Integer>();
         map.put(-5, -5);
         map.putAll(mapTocopy);
         return map.size();
     }
}

Any ideas for missed corner-cases or some good tests?

-- 
Michal Vala
OpenJDK QE
Red Hat Czech


More information about the core-libs-dev mailing list