RFR 8200696 : Optimal initial capacity of java.lang.Class.enumConstantDirectory

David Holmes david.holmes at oracle.com
Wed Apr 4 03:15:12 UTC 2018


On 4/04/2018 1:06 PM, Ivan Gerasimov wrote:
> Hi David!
> 
> 
> On 4/3/18 6:41 PM, David Holmes wrote:
>> Hi Ivan,
>>
>> On 4/04/2018 10:01 AM, Ivan Gerasimov wrote:
>>> Hi David!
>>>
>>>
>>> On 4/3/18 4:49 PM, David Holmes wrote:
>>>> Hi Ivan,
>>>>
>>>> On 4/04/2018 9:22 AM, Ivan Gerasimov wrote:
>>>>> Hello!
>>>>>
>>>>> Yet another occurrence of not-optimally pre-sized HashMap.
>>>>>
>>>>> When java.lang.Class.enumConstantDirectory is created, the initial 
>>>>> capacity is set to be (2 * universe.length), which is more than 
>>>>> necessary in some cases.
>>>>>
>>>>> Choosing the capacity optimally will allow us to save a few bytes 
>>>>> with some enum classes.
>>>>
>>>> How are you defining optimal? 
>>> By optimal I meant the minimum value that will not make the internal 
>>> storage to be reallocated during insertion.
>>>
>>> Here's a quotation from the documentation [1]:
>>> "If the initial capacity is greater than the maximum number of 
>>> entries divided by the load factor, no rehash operations will ever 
>>> occur."
>>>
>>> Given the default load factor 0.75, the formula (expectedSize / 0.75 
>>> + 1) gives us the optimal initial capacity.
>>
>> Isn't it simpler to just do:
>>
>> new HashMap(universe.length, 1.0f);
>>
>> and change the load factor? Otherwise you have to allow for an extra 
>> 25% of space, and that is before it expands to be a power of 2 IIUC.
>>
> Yes, it would be simpler of course.
> However, the chance of a collision will also increase then.
> Especially in cases when the number of entries is close (but not greater 
> than) to a power of 2.
> 
> Not sure if it matters in this particular case, as the number of enum 
> values is likely to be relatively small, so the lookup will be fast anyway.
> But I thought it would be better to keep the default load factor and 
> just set the initial capacity to the optimal value: minimum while not 
> causing reallocations during insertion.

Okay. Thanks for explaining. The code could do with a comment explaining 
this, and the bug report certainly should explain it.

Thanks,
David

> With kind regards,
> Ivan
> 
>> David
>>
>>> The testlibrary class testlibrary/OptimalCapacity.java is used to 
>>> make sure that the chosen initial capacity is neither too low (so 
>>> that no reallocations happen) nor too high (no memory is wasted).
>>>
>>> With kind regards,
>>> Ivan
>>>
>>> [1] https://docs.oracle.com/javase/10/docs/api/java/util/HashMap.html
>>>
>>>
>>>> The bug report only gives one example where the current calculation 
>>>> produces a too large value. If the HashMap itself rounds up the 
>>>> initial capacity to a power of 2, how much extra space do we need 
>>>> compared to universe.length? Do we just need to pass 
>>>> (universe.length+1) to get the smallest power of 2 greater than 
>>>> universe.length?
>>>>
>>>> Thanks,
>>>> David
>>>>
>>>>> Would you please help review this trivial fix?
>>>>>
>>>>> BUGURL: https://bugs.openjdk.java.net/browse/JDK-8200696
>>>>> WEBREV: http://cr.openjdk.java.net/~igerasim/8200696/00/webrev/
>>>>>
>>>>
>>>
>>
> 


More information about the core-libs-dev mailing list