HashMap implementations and Integer specializations
charlie hunt
charlie.hunt at sun.com
Mon Jun 9 22:38:56 UTC 2008
Martin,
I'll accept your adding of the comment as a solution to my suggested
improvement.
charlie ...
P.S. I sense you did not like my feedback / comments, or were somehow
offended. I was trying to offer you a suggestion to improve to your test
case.
Martin Buchholz wrote:
> Charlie,
>
> Test case code is different from regular code
> in that bad practice is often a good idea.
> People should know better than to "fix" test cases
> using their IDE.
>
> But I added this comment:
>
> // This code intentionally uses the denigrated constructors
> // that are guaranteed to return a unique object!
>
> Martin
>
> On Mon, Jun 9, 2008 at 11:26 AM, charlie hunt <charlie.hunt at sun.com> wrote:
>
>> Martin,
>>
>> I'm rather shocked at your response!
>>
>> Consider for example, there's a very popular tool out their that integrates
>> very well into NetBeans IDE and Eclipse IDE which suggests changing all
>> 'new Integer(), new Long()' calls into 'Integer.valueOf() & Long.valueOf()'.
>> Take a quick look at how new Integer() contrasts with Integer.valueOf().
>>
>> Suppose in the future as Martin moves on to bigger and better things beyond
>> OpenJDK and a future maintainer looks at your test case and updates it to
>> use Integer.valueOf() and Long.valueOf() as result of such a tool mentioned
>> above. Should that happen, I don't think your test case would test what it
>> was intended to test.
>>
>> Would not your test case be improved by choosing values well outside the
>> values contained in the IntegerCache & LongCache?
>>
>> charlie ...
>>
>> Martin Buchholz wrote:
>>
>>> Charlie,
>>>
>>> Hotspot engineers throughout the ages
>>> have been tempted to optimize away
>>> object identity semantics of Integer and String,
>>> but I'm pretty sure that for e.g. new Integer(x)
>>> and new String(y) hotspot will certainly continue
>>> to return _new_ objects (unless of course
>>> the application can be proven to not tell the
>>> difference), and there are sufficient
>>> regression tests to keep all of us in line.
>>>
>>> Martin
>>>
>>> On Mon, Jun 9, 2008 at 7:57 AM, charlie hunt <charlie.hunt at sun.com> wrote:
>>>
>>>
>>>> wrt the Integer & Long values you use in your test case ...
>>>>
>>>> You might consider using larger Integer & Long values, ones that lie
>>>> outside
>>>> the range of Integer.IntegerCache & Long.LongCache to avoid any potential
>>>> confusion about whether the values you are putting into the Map might get
>>>> grabbed from the IntegerCache or LongCache via some "magic" of the
>>>> HotSpot
>>>> compiler, i.e it's conceivable a call to 'new Integer()' could be
>>>> transformed into Integer.valueOf()'.
>>>>
>>>> charlie ...
>>>>
>>>> Martin Buchholz wrote:
>>>>
>>>>
>>>>> JavaOne 2008 technical session PDFs are now available
>>>>>
>>>>>
>>>>>
>>>>> http://developers.sun.com/learning/javaoneonline/j1online.jsp?track=javase&yr=2008
>>>>>
>>>>> I was surprised to discover a discussion of
>>>>> HashMap optimization at the JavaOne talk
>>>>> http://developers.sun.com/learning/javaoneonline/2008/pdf/TS-6434.pdf
>>>>>
>>>>> Did I miss an announcement of that?
>>>>>
>>>>> A comment on that talk:
>>>>>
>>>>> It is easy to make the mistake of thinking that HashMap does not
>>>>> have to store the actual Integer key in the call to put.
>>>>> Unfortunately, Java's evil semantics (everything is an Object,
>>>>> everything is a Lock, everything has an Identity) require
>>>>> that the exact same objects inserted into a HashMap can be
>>>>> removed later. This means that specialized submaps will have
>>>>> a harder time optimizing for footprint. (I do think the
>>>>> algorithm presented in the talk is correct, since the front cache
>>>>> is likely only used for get(), and not, e.g. for entrySet().iterator())
>>>>>
>>>>> I intend to check in a test case modification that will ensure
>>>>> that future optimizations do not violate the current compatibility
>>>>> guarantees.
>>>>>
>>>>> diff --git a/test/java/util/Collection/MOAT.java
>>>>> b/test/java/util/Collection/MOAT.java
>>>>> --- a/test/java/util/Collection/MOAT.java
>>>>> +++ b/test/java/util/Collection/MOAT.java
>>>>> @@ -544,6 +544,27 @@ public class MOAT {
>>>>> check(m.size() != 0 ^ m.isEmpty());
>>>>> }
>>>>>
>>>>> + private static void testPutPreversesObjectIdentity(Map<?,?> m,
>>>>> + Object key,
>>>>> + Object val) {
>>>>> + try {
>>>>> + Map<Object,Object> m2 = m.getClass().newInstance();
>>>>> + m2.put(key, val);
>>>>> + Map.Entry<Object,Object> e =
>>>>> m2.entrySet().iterator().next();
>>>>> + check(e.getKey() == key);
>>>>> + check(e.getValue() == val);
>>>>> + check(m2.keySet().iterator().next() == key);
>>>>> + check(m2.values().iterator().next() == val);
>>>>> + } catch (Throwable t) { unexpected(t); }
>>>>> + }
>>>>> +
>>>>> + private static void testPutPreversesObjectIdentity(Map<?,?> m) {
>>>>> + testPutPreversesObjectIdentity(m, new Integer(42), new
>>>>> Integer(43));
>>>>> + testPutPreversesObjectIdentity(m, new Long(42L), new
>>>>> Long(43L));
>>>>> + testPutPreversesObjectIdentity(m, new Double(42.0), new
>>>>> Double(43.0));
>>>>> + testPutPreversesObjectIdentity(m, new String("42"), new
>>>>> String("43"));
>>>>> + }
>>>>> +
>>>>> private static void testMap(Map<Integer,Integer> m) {
>>>>> System.out.println("\n==> " + m.getClass().getName());
>>>>>
>>>>> @@ -572,6 +593,7 @@ public class MOAT {
>>>>> }
>>>>>
>>>>> if (supportsPut(m)) {
>>>>> + testPutPreversesObjectIdentity(m);
>>>>> try {
>>>>> check(m.put(3333, 77777) == null);
>>>>> check(m.put(9134, 74982) == null);
>>>>>
>>>>>
>>>>>
>>>> --
>>>>
>>>> Charlie Hunt
>>>> Java Performance Engineer
>>>>
>>>> <http://java.sun.com/docs/performance/>
>>>>
>>>>
>>>>
>>>>
>> --
>>
>> Charlie Hunt
>> Java Performance Engineer
>>
>> <http://java.sun.com/docs/performance/>
>>
>>
>>
--
Charlie Hunt
Java Performance Engineer
<http://java.sun.com/docs/performance/>
More information about the core-libs-dev
mailing list