<p dir="ltr">You should use System.nanoTime instead of currentTimeMillis.</p>
<p dir="ltr">In your 2nd run, you&#39;re going to either get a branch mispredict when it switches from Integer to Object (shouldn&#39;t be big contributor though) or you&#39;re possibly causing JIT to do type checks on each iteration to see which hashCode to call (assuming there&#39;s an inline cache installed).</p>

<p dir="ltr">Why don&#39;t you make the array typed Object but fill it only with Integers? Why are you mixing in two types?</p>
<p dir="ltr">Sent from my phone</p>
<div class="gmail_quote">On May 13, 2013 1:30 PM, &quot;Andy Nuss&quot; &lt;<a href="mailto:andrew_nuss@yahoo.com">andrew_nuss@yahoo.com</a>&gt; wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div style="font-size:12pt;font-family:times new roman,new york,times,serif"><div><span>Here&#39;s my benchmarking code.  I don&#39;t see at all why a virtual call to Integer.hashCode is so much slower than the base line loop skeleton + inline access to member value of Integer (3rd case) + 0.5 nanos of vtable call (measured in a separate benchmark).</span></div>
<div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br><span></span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">
<span>To me, this indicates a serious design flaw in so-called intrinsic call on modern fast machines that could be corrected (were it possible) by making hashCode() a normal non-native function that forwards to
 System.identityHashCode().<br></span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br><span></span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">
<span>...</span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br><span></span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">
<span>package test;<br><br>public class Test {<br>    <br>    private static final int        LEN = 64;<br>    private static final int   
     HALFLEN = LEN/2;<br>    private static final int        MASK = HALFLEN-1;<br>    private static final long        TENGIG = 10000000000L;<br>    <br>    private static int sum (Object[] ar, long cnt, int mask)<br>    {<br>
        int sum = 0;<br>        for (long i = 0; i &lt; cnt; i++)<br>            sum += ar[(int)i &amp; mask].hashCode();<br>        return sum;<br>    }<br>    <br>    private static int sum (Integer[] ar, long cnt, int mask)<br>
    {<br>        int sum = 0;<br>        for (long i = 0; i &lt; cnt; i++)<br>   
         sum += ar[(int)i &amp; mask].hashCode();<br>        return sum;<br>    }<br>    <br>    public static void main (String[] args)<br>    {<br>        Object[] ar1 = new Object[LEN];<br>        for (int i = 0; i &lt; LEN; i++)<br>
            ar1[i] = new Object();<br>        Object[] ar2 = new Object[LEN];<br>        for (int i = 0; i &lt; LEN; i++)<br>            ar2[i] = i &lt; HALFLEN ? new Integer(i) : new Object();<br>        Integer[] ar3 = new Integer[LEN];<br>
        for (int i = 0; i &lt; LEN; i++)<br>           
 ar3[i] = new Integer(i);<br>        <br>        long m1, m2;<br>        int sum = 0;<br>        <br>        for (int i = 0; i &lt; 10000; i++)<br>            sum += sum(ar1, 10000, MASK);<br>        m1 = System.currentTimeMillis();<br>
        sum += sum(ar1, TENGIG, MASK);<br>        m2 = System.currentTimeMillis();<br>        System.out.println(&quot;Object.hashCode() &quot; + (m2-m1));<br>        <br>        for (int i = 0; i &lt; 10000; i++)<br>            sum += sum(ar2, 10000, MASK);<br>
        m1 =
 System.currentTimeMillis();<br>        sum += sum(ar2, TENGIG, MASK);<br>        m2 = System.currentTimeMillis();<br>        System.out.println(&quot;vtable using Integer.hashCode() &quot; + (m2-m1));<br>        <br>        for (int i = 0; i &lt; 10000; i++)<br>
            sum += sum(ar3, 10000, MASK);<br>        m1 = System.currentTimeMillis();<br>        sum += sum(ar3, TENGIG, MASK);<br>        m2 = System.currentTimeMillis();<br>        System.out.println(&quot;inline using Integer.hashCode() &quot; + (m2-m1));<br>
        System.out.println(&quot;just to make sure everything executes &quot; + sum);<br>   
 }<br>}<br><br></span></div><div><br></div>  <div style="font-family:times new roman,new york,times,serif;font-size:12pt"> <div style="font-family:times new roman,new york,times,serif;font-size:12pt"> <div dir="ltr"> <hr size="1">
  <font face="Arial"> <b><span style="font-weight:bold">From:</span></b> Vitaly Davidovich &lt;<a href="mailto:vitalyd@gmail.com" target="_blank">vitalyd@gmail.com</a>&gt;<br> <b><span style="font-weight:bold">To:</span></b> Andy Nuss &lt;<a href="mailto:andrew_nuss@yahoo.com" target="_blank">andrew_nuss@yahoo.com</a>&gt; <br>
<b><span style="font-weight:bold">Cc:</span></b> hotspot compiler &lt;<a href="mailto:hotspot-compiler-dev@openjdk.java.net" target="_blank">hotspot-compiler-dev@openjdk.java.net</a>&gt; <br> <b><span style="font-weight:bold">Sent:</span></b> Monday, May 13, 2013 10:20 AM<br>
 <b><span style="font-weight:bold">Subject:</span></b> Re: performance surprise with Object.hashCode()<br> </font> </div> <div><br>
<div><div dir="ltr">Object.hashCode is an intrinsic (see libraryCall.cpp), so it makes sense you don&#39;t see any difference with your changes.</div>
<div dir="ltr">Looking at the assembly, when it knows statically that Integer is receiver it simply reads the value field inline.  When it doesn&#39;t know, it loads the address of the receiver&#39;s hashCode method and compares against Object.hashCode.  If equal, then it proceeds with pulling hash out of header.  If it&#39;s not, it jumps to a vcall and then jumps again to function prologue.  I don&#39;t really see why you&#39;d get such a large discrepancy.  The only thing is that if hashCode is overridden it jumps around a bit and may get icache miss, but that would happen with plain vcall too.  So basically only thing &quot;special&quot; (in terms of vcall) I see for hashCode is a check against an immediate (for seeing if hashCode is overridden or not), a forward (short) jump to skip native object.hashCode impl and that&#39;s it.</div>


<div dir="ltr">Sent from my phone</div>
<div>On May 13, 2013 11:45 AM, &quot;Andy Nuss&quot; &lt;<a rel="nofollow" href="mailto:andrew_nuss@yahoo.com" target="_blank">andrew_nuss@yahoo.com</a>&gt; wrote:<br><blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div><div style="font-size:12pt;font-family:times new roman,new york,times,serif"><div>Hi,</div><div><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

I was profiling various aspects of the JVM and hit a big surprise.</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

* on my corei7, virtual calls are about .5 nanos</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">* when a class has not derived a new behavior for hashCode(),
 this hashCode call is 1.5 nanos because native</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">* for java.lang.Integer, which just returns the intValue(), hashCode is zero time when hotspot can inline</div>

<div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">(that is about one clock cycle when testing hits the same Integer instances keeping them in L1 cache)<br>

</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">* but when you force HotSpot to go thru the vtable for Integer.hashCode, the call grows to 4 nanos!</div>

<div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

The last case was a big surprise, as I thought for Integer, a vcall to hashCode would only cost the 0.5 nanos of the vtable.</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

<br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">Somehow, native code is involved even when hashCode() has been subclassed to not be native.<br>

</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

...</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

Then I tried mucking with the code in openjdk.  I compiled the sources.  I edited Object.java to be this:</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

<br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">public class Object {</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

    public int hashCode ()</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">    {</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

         return System.identityHashCode(this);</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">    }</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

}</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

To me, this seems like an ideal fix to this serious performance bug, making the entry point NON-native, but having the same effect by default.  So that if you subclass, you are sure not to pay a doubled(!) native cost.</div>

<div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

But changing the source code had no effect on the results.  Nor did it have any affect on /share/native/java/lang/Object.c.</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

<br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">In both cases, with and without my change to the definition of Object.java, Object.c has NO native function definition for the hashCode function.</div>

<div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

This leads me to believe that this performance defect is endemic to the hotspot compiler code itself, in that it special cases the Object.hashCode() function.</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

<br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">It seems that if somehow this performance defect (as I see it) where fixed, String hashing and Integer hashing and the like for classes which cache their hashvalue would be greatly improved.</div>

<div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

???</div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif"><br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:times new roman,new york,times,serif">

Andy</div></div></div></blockquote></div>
</div><br><br></div> </div> </div>  </div></div></blockquote></div>