RFR 8005698 : Handle Frequent HashMap Collisions with Balanced Trees
Paul Sandoz
paul.sandoz at oracle.com
Tue Jun 4 07:56:50 UTC 2013
I forgot to say please don't let this hold up getting the patch into TL. I think it more important to get the code in then iterate on it.
Paul.
On Jun 4, 2013, at 9:45 AM, Paul Sandoz <paul.sandoz at oracle.com> wrote:
> Hi,
>
> On Jun 4, 2013, at 1:34 AM, Brent Christian <brent.christian at oracle.com> wrote:
>
>> Hi, Paul
>>
>> If a HashMap is created via serialization or clone(), we don't check if the table needs resizing when adding entries, but still need to check if a bin should be converted to a TreeBin. In this case, putForCreate() calls createEntry() directly, instead of addEntry().
>>
>
> But putForCreate calculates "checkIfNeedTree":
> 1161 if (table[i] instanceof Entry) {
> 1162 int listSize = 0;
> 1163 Entry<K,V> e = (Entry<K,V>) table[i];
> 1164 for (; e != null; e = (Entry<K,V>)e.next) {
> 1165 Object k;
> 1166 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
> 1167 e.value = value;
> 1168 return;
> 1169 }
> 1170 listSize++;
> 1171 }
> 1172 // Didn't find, fall through to createEntry().
> 1173 // Check for conversion to TreeBin done via createEntry().
> 1174 checkIfNeedTree = listSize >= TreeBin.TREE_THRESHOLD;
> 1175 } else if (table[i] != null) {
> ...
> 1186
> 1187 createEntry(hash, key, value, i, checkIfNeedTree);
> 1188 }
>
> So the call to createEntry is just recalculating the same "listSize" value:
>
> 2232 void createEntry(int hash, K key, V value, int bucketIndex, boolean checkIfNeedTree) {
>
> ...
> 2239 if (checkIfNeedTree) {
> 2240 int listSize = 0;
> 2241 for (e = (Entry<K,V>) table[bucketIndex]; e != null; e = (Entry<K,V>)e.next) {
> 2242 listSize++;
> 2243 if (listSize >= TreeBin.TREE_THRESHOLD) { // Convert to TreeBin
> 2244 if (comparableClassFor(key) != null) {
> 2245 TreeBin t = new TreeBin();
> 2246 t.populate((Entry)table[bucketIndex]);
> 2247 table[bucketIndex] = t;
> 2248 }
> 2249 break;
> 2250 }
> 2251 }
> 2252 }
> Paul.
>
>> Thanks,
>> -Brent
>>
>> On 6/3/13 12:56 AM, Paul Sandoz wrote:
>>> Hi Brent,
>>>
>>> A minor thing: take it or leave it :-)
>>>
>>> In HashMap:
>>>
>>> 2207 void addEntry(int hash, K key, V value, int bucketIndex, boolean checkIfNeedTree) {
>>> 2208 // assert key != null;
>>> 2209 if ((size >= threshold) && (null != table[bucketIndex])) {
>>> 2210 resize(2 * table.length);
>>> 2211 hash = hash(key);
>>> 2212 bucketIndex = indexFor(hash, table.length);
>>> 2213 }
>>> 2214 createEntry(hash, key, value, bucketIndex, checkIfNeedTree);
>>> 2215 }
>>>
>>> You could re-verify the bucket size if the table is resized rather
>> than in createEntry, since that AFAICT is the only case where conditions
>> after the call to addEntry might change.
>>>
>>> Pau.
>>>
>
More information about the core-libs-dev
mailing list