On Apr 9 2013, at 19:56 , Martin Buchholz wrote:

> Mike, thanks.
> 
> I don't see anything wrong in this version, although the ongoing 
> complexification and special-case-ification (with attendant risk of bugs) of 
> ArrayList and HashMap, the two most didactically important classes, continue 
> to bother me.  This change continues to feel marginal.  

It was surprising to find just how many ArrayList and HashMap instances were 
empty and/or never used. Unfortunately it's harder to globally fix applications 
than it is to and special case code to ArrayList and HashMap.

> Anyways, this is OK with me if it's OK with Alan.
> 
> The original code that shifts by one every time has a certain elegance, and 
> because it's rare to need more than one doubling, is also hard to beat 
> performance-wise.
> 
>  546             while (newCapacity < targetCapacity)
>  547                 newCapacity <<= 1;
I will restore it.

> There are now so many "if (isEmpty())" checks that I wonder again whether it 
> would be better to use a null for the empty table, since null checks are 
> closer to free.

The use of an empty array rather than null was suggested by John Rose who said:

> I recommend an empty array rather than null as a sentinel value for two 
> reasons:
> 
> 1. The JVM prefers to merge null checks into load or store instructions 
> (so-called "implicit null checks") because it removes an explicit branch. But 
> it only does so if the probability of nulls is zero or very low. But using 
> null as a sentinel for common states (e.g., empty collection) defeats this 
> optimization.
> 
> 2. For power-of-two sized structures (HashMap) we can optimize away an array 
> range check in the presence of a zero-length check. 
> 
> Since most uses of a variable-sized collection load and test the array 
> length, the sentinel check can easily be overloaded onto this test. If null 
> is not used, then the (safety-mandated) null check is (usually) merged into 
> the load of the length. If the table is power-of-two-sized, then only the 
> zero check remains, and the array range check may be removed. This is thought 
> to be the best code for a frequent load from a possibly-empty collection.
> 
> Mike asked, "what about empty collection?" This is a reasonable thing to use, 
> but it has a cost. The JVM uses inline caches and type profiles to simplify 
> its optimized code; these techniques "win" when at a given use point 
> (individual call to Map.get, for example) there is only one class present, 
> even if the interface is totally general. (This is the so-called 
> "monomorphic" case.) If the application uses (say) only HashMaps for both 
> empty and non-empty maps, then this optimization can win big. It can be 
> broken, on the other hand, if the application begins to use one other type 
> for some other case (such as empty maps). In these cases, it is better to 
> overload the "am I empty?" test on some other loaded value, such as a null or 
> (better) an array length. 

Mike

Reply via email to