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

Michal Vala mvala at redhat.com
Wed Dec 12 13:36:33 UTC 2018


thank you Roger, I've added jmh benchmark. see new webrev in reply to Martin's 
review.


On 12/12/18 4:45 AM, Roger Riggs wrote:
> Hi,
> 
> fyi, jmh tests appropriate for JDK apis are located in the test/micro/... 
> directories.
> 
> The benchmarks are built with:
>    % make build-microbenchmark
> 
> The results are in the build/<platform>/images/test/micro/benchmarks.jar
> 
> $.02, Roger
> 
> On 12/11/2018 A 9:55 PM, Martin Buchholz wrote:
>> Hi Michal, pleased to meet you.  I'll be your sponsor.
>>
>> The test will need a legal header, presumably similar to others authored by
>> redhatters.
>>
>> It is now possible to check in jmh microbenchmarks (but I've never done so
>> myself).
>>
>> The current coding style is non-standard, but deliberate; avoid gratuitous
>> changes like
>> -                Node<K,V> e;
>> +                Node<K, V> e;
>>
>> As author of concurrent/ConcurrentHashMap/WhiteBox.java ...
>> - I thought you'd need a @modules ... did this test actually pass?
>> - you should have some kind of @summary that includes the word "whitebox"
>> - why not "throws ReflectiveOperationException" ?
>> - your reviewer is a bit on the autistic side, so please change /** to /*
>> on the @test comment (it's not javadoc!)
>>
>>
>> On Tue, Dec 11, 2018 at 11:06 AM Michal Vala <mvala at redhat.com> wrote:
>>
>>> 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
>>>
> 

-- 
Michal Vala
OpenJDK QE
Red Hat Czech


More information about the core-libs-dev mailing list