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