<p>Correct - I was pointing out the general case where such analysis would be useful as well (good amount of code makes defensive copies just in case, so runtime analysis would be beneficial).</p>
<p>Sent from my phone</p>
<div class="gmail_quote">On Mar 28, 2012 11:00 AM, &quot;Rémi Forax&quot; &lt;<a href="mailto:forax@univ-mlv.fr">forax@univ-mlv.fr</a>&gt; wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On 03/28/2012 04:53 PM, Vitaly Davidovich wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
clone() could be removed but the issue is whether the JVM does enough analysis to see that - I think enough inlining has to occur such that clone() is inlined right into bar() and then the JVM can see that it doesn&#39;t escape and the array is not mutated.  Either the allocation/copy is removed or at least becomes stack allocated.<br>

<br>
Wrinkle with clone() is that it&#39;s virtual so if the inline cache is exceeded and regular vtbl call is made, we lose this ability; that&#39;s a more general case and shouldn&#39;t happen with things like bar().<br>
<br>
</blockquote>
<br>
Technically here, the JIT can easily prove the exact type of the array (the receiver of clone()),<br>
so clone() is like if you have only one implementation method so there is no need to create a guard<br>
(but I know that Hotspot doesn&#39;t do that, that&#39;s why Array.copyOf() is a little faster than clone()).<br>
<br>
Rémi<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Sent from my phone<br>
<br>
On Mar 28, 2012 10:43 AM, &quot;Roel Spilker&quot; &lt;<a href="mailto:r.spilker@gmail.com" target="_blank">r.spilker@gmail.com</a> &lt;mailto:<a href="mailto:r.spilker@gmail.com" target="_blank">r.spilker@gmail.com</a>&gt;&gt; wrote:<br>

<br>
    Rémi, are you sure the clone call can be removed? I agree that<br>
    that would even be better for hotspot JVMs that use escape<br>
    analysis. That said, apart from engineering effort, if a synthetic<br>
    inner class is used you get the benefit immediately, even on VMs<br>
    that cannot afford escape analysis.<br>
<br>
    Roel<br>
<br>
<br>
    On Wed, Mar 28, 2012 at 4:13 PM, Rémi Forax &lt;<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a><br>
    &lt;mailto:<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>&gt;&gt; wrote:<br>
<br>
        On 03/28/2012 03:39 PM, Roel Spilker wrote:<br>
<br>
            Hi all,<br>
<br>
            TL;DR: for (Edge edge : Edge.values()) copies an array<br>
            every time it is executed. This can be prevented. Is that<br>
            a good idea and how to proceed from here?<br>
<br>
            I&#39;m new to this list, so please let me know if this is not<br>
            the place to post this.<br>
<br>
            When I was profiling our application I notices that we<br>
            allocate quite some memory when iterating over enum<br>
            values. The pattern used was:<br>
<br>
            class  Foo {<br>
             void bar() {<br>
               for (Edge e : Edge.values()) {<br>
                 // do some work<br>
               }<br>
             }<br>
            }<br>
<br>
            The call to Edge.values() obviously creates a new clone of<br>
            the Edge[] containing all enum constants. So we&#39;ve<br>
            modified our code:<br>
<br>
            class  Foo {<br>
             private static final Edge[] EDGES = Edge.values();<br>
             void bar() {<br>
               for (Edge e : EDGES) {<br>
                 // do some work<br>
               }<br>
             }<br>
            }<br>
<br>
            This solves our allocation problem, but it is not a nice<br>
            solution. Since code in the enhanced-for has no way to<br>
            modify the array this pattern can be done at compile-time.<br>
            A synthetic inner class can be generated to keep the copy<br>
            of the array. The desugared (pseudo) code would then look<br>
            something like this:<br>
<br>
            /* syncthetic */ class Foo$0 {<br>
             static final Edge[] EDGES = Edge.values();<br>
            }<br>
<br>
            class  Foo {<br>
             void bar() {<br>
               for (Edge e : Foo$0.EDGES) {<br>
                 // do some work<br>
               }<br>
             }<br>
            }<br>
<br>
            There is precedence for this kind of<br>
            desugaring/optimization: When you use an enum-in-switch, a<br>
            synthetic class is generated containing an int array for<br>
            the ordinals.<br>
<br>
            I have a few questions:<br>
            - Do you think this is a good optimization? The trade-off<br>
            here is creating a copy every time the enhanced-for is<br>
            used (could be in an inner loop) versus the overhead of<br>
            loading an extra class.<br>
            - Is there a better optimization possible/required?<br>
            EnumSet uses<br>
            SharedSecrets.<u></u>getJavaLangAccess().<u></u>getEnumConstantsShared(<u></u>elementType),<br>
            but that won&#39;t work in user code.<br>
            - If it is a good idea, how do I proceed from here?<br>
            Possibly create a JEP? How can I contribute? Who wants to<br>
            support?<br>
<br>
            Roel Spilker<br>
<br>
<br>
        Hi Roel,<br>
        There are several issues with your template, EDGES is<br>
        initialized too soon, i.e.<br>
        even if you don&#39;t call bar() and stay too long, i.e even if<br>
        you never call bar() more than once.<br>
<br>
        I think it&#39;s better to let the the escape analysis pass done<br>
        by the JIT to inline<br>
        values() and remove the call to clone().<br>
<br>
        Rémi<br>
<br>
<br>
<br>
<br>
<br>
</blockquote>
<br>
</blockquote></div>