<p dir="auto">If I have a function prototype something like this:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="doit(a::Array{Tuple{Int, MyType}, 1}, b::Int, c::MyType)"><pre class="notranslate"><code class="notranslate">doit(a::Array{Tuple{Int, MyType}, 1}, b::Int, c::MyType)
</code></pre></div>
<p dir="auto">where MyType is an ordinary Julia GC/heap allocated type, then the following line of code within the function seems to lead to a heap allocation of a tuple (the same is the case for any immutable type).</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="a[1] = b, c"><pre class="notranslate"><code class="notranslate">a[1] = b, c
</code></pre></div>
<p dir="auto">There seem to be two issues here:</p>
<ol dir="auto">
<li>
<p dir="auto">There seems to be no efficient way to write an immutable value directly into an array in Julia. The above shouldn't require any allocation of any kind, stack or heap.</p>
</li>
<li>
<p dir="auto">Apparently, Julia GC/heap-allocates immutables if they contain heap references. I don't understand why, since surely the GC scans the stack conservatively for pointers.</p>
</li>
</ol>
<p dir="auto">Anyway, I have been unable to find a ticket or PR which deals with the above serious performance issue (which we hit in practice), directly.</p>
<p dir="auto">(Obliquely) relevant tickets/PRs/tickets seem to include [1]. [2], [3] and [4] and of course the tupocalypse itself. There are also some relevant sounding things on Jeff's compiler optimisation tracker [5], though I am not clear if any are directly relevant.</p>
<p dir="auto">[1] <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="41144467" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/8134" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/8134/hovercard" href="https://github.com/JuliaLang/julia/pull/8134">#8134</a><br>
[2] <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="95850049" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/12205" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/12205/hovercard" href="https://github.com/JuliaLang/julia/pull/12205">#12205</a><br>
[3] <a href="https://groups.google.com/forum/#!topic/julia-users/F_ncyfP2vxg" rel="nofollow">https://groups.google.com/forum/#!topic/julia-users/F_ncyfP2vxg</a><br>
[4] <a href="https://groups.google.com/forum/#!topic/julia-users/LthfABeDN50" rel="nofollow">https://groups.google.com/forum/#!topic/julia-users/LthfABeDN50</a><br>
[5] <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="15674221" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/3440" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/3440/hovercard" href="https://github.com/JuliaLang/julia/issues/3440">#3440</a></p>
<p dir="auto">Using <code class="notranslate">enumerate</code> to iterate through array of mutable objects allocates, but using a simple for loop does not:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="type MyMutable
  a::Int
end

immutable MyImmutable
  a::Int
end

function sumit(arr)
  val = 0
  for i=1:length(arr)
    val += arr[i].a
  end

  return val
end

function sumit2(arr)
  val = 0
  for (i, obj) in enumerate(arr)
    val += obj.a
  end

  return val
end

nel = 5000
arr = Array(MyMutable, nel)
arr2 = Array(MyImmutable, nel)
for i=1:nel
  arr[i] = MyMutable(i)
  arr2[i] = MyImmutable(i)
end

# warmup
@time sumit(arr)
@time sumit(arr2)
@time sumit2(arr)
@time sumit2(arr2)

println(&quot;\nfinal times:&quot;)
@time sumit(arr)
println(&quot;  mutable explicit for loop @time printed above\n&quot;)

@time sumit(arr2)
println(&quot;  immutable explicit for loop @time printed above\n&quot;)

@time sumit2(arr)
println(&quot;  mutable enumerate @time printed above\n&quot;)

@time sumit2(arr2)
println(&quot;  immutable enumerate @time printed above\n&quot;)"><pre class="notranslate">type MyMutable
  a<span class="pl-k">::</span><span class="pl-c1">Int</span>
<span class="pl-k">end</span>

immutable MyImmutable
  a<span class="pl-k">::</span><span class="pl-c1">Int</span>
<span class="pl-k">end</span>

<span class="pl-k">function</span> <span class="pl-en">sumit</span>(arr)
  val <span class="pl-k">=</span> <span class="pl-c1">0</span>
  <span class="pl-k">for</span> i<span class="pl-k">=</span><span class="pl-c1">1</span><span class="pl-k">:</span><span class="pl-c1">length</span>(arr)
    val <span class="pl-k">+=</span> arr[i]<span class="pl-k">.</span>a
  <span class="pl-k">end</span>

  <span class="pl-k">return</span> val
<span class="pl-k">end</span>

<span class="pl-k">function</span> <span class="pl-en">sumit2</span>(arr)
  val <span class="pl-k">=</span> <span class="pl-c1">0</span>
  <span class="pl-k">for</span> (i, obj) <span class="pl-k">in</span> <span class="pl-c1">enumerate</span>(arr)
    val <span class="pl-k">+=</span> obj<span class="pl-k">.</span>a
  <span class="pl-k">end</span>

  <span class="pl-k">return</span> val
<span class="pl-k">end</span>

nel <span class="pl-k">=</span> <span class="pl-c1">5000</span>
arr <span class="pl-k">=</span> <span class="pl-c1">Array</span>(MyMutable, nel)
arr2 <span class="pl-k">=</span> <span class="pl-c1">Array</span>(MyImmutable, nel)
<span class="pl-k">for</span> i<span class="pl-k">=</span><span class="pl-c1">1</span><span class="pl-k">:</span>nel
  arr[i] <span class="pl-k">=</span> <span class="pl-c1">MyMutable</span>(i)
  arr2[i] <span class="pl-k">=</span> <span class="pl-c1">MyImmutable</span>(i)
<span class="pl-k">end</span>

<span class="pl-c"><span class="pl-c">#</span> warmup</span>
<span class="pl-c1">@time</span> <span class="pl-c1">sumit</span>(arr)
<span class="pl-c1">@time</span> <span class="pl-c1">sumit</span>(arr2)
<span class="pl-c1">@time</span> <span class="pl-c1">sumit2</span>(arr)
<span class="pl-c1">@time</span> <span class="pl-c1">sumit2</span>(arr2)

<span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span><span class="pl-cce">\n</span>final times:<span class="pl-pds">"</span></span>)
<span class="pl-c1">@time</span> <span class="pl-c1">sumit</span>(arr)
<span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>  mutable explicit for loop @time printed above<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>)

<span class="pl-c1">@time</span> <span class="pl-c1">sumit</span>(arr2)
<span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>  immutable explicit for loop @time printed above<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>)

<span class="pl-c1">@time</span> <span class="pl-c1">sumit2</span>(arr)
<span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>  mutable enumerate @time printed above<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>)

<span class="pl-c1">@time</span> <span class="pl-c1">sumit2</span>(arr2)
<span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>  immutable enumerate @time printed above<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>)</pre></div>
<p dir="auto">results:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="final times:
  0.000043 seconds (5 allocations: 176 bytes)
  mutable explicit for loop @time printed above

  0.000009 seconds (5 allocations: 176 bytes)
  immutable explicit for loop @time printed above

  0.000123 seconds (10.01 k allocations: 312.688 KB)
  mutable enumerate @time printed above

  0.000008 seconds (6 allocations: 192 bytes)
  immutable enumerate @time printed above"><pre class="notranslate">final times<span class="pl-k">:</span>
  <span class="pl-c1">0.000043</span> seconds (<span class="pl-c1">5</span> allocations<span class="pl-k">:</span> <span class="pl-c1">176</span> bytes)
  mutable explicit <span class="pl-k">for</span> loop <span class="pl-c1">@time</span> printed above

  <span class="pl-c1">0.000009</span> seconds (<span class="pl-c1">5</span> allocations<span class="pl-k">:</span> <span class="pl-c1">176</span> bytes)
  immutable explicit <span class="pl-k">for</span> loop <span class="pl-c1">@time</span> printed above

  <span class="pl-c1">0.000123</span> seconds (<span class="pl-c1">10.01</span> k allocations<span class="pl-k">:</span> <span class="pl-c1">312.688</span> KB)
  mutable enumerate <span class="pl-c1">@time</span> printed above

  <span class="pl-c1">0.000008</span> seconds (<span class="pl-c1">6</span> allocations<span class="pl-k">:</span> <span class="pl-c1">192</span> bytes)
  immutable enumerate <span class="pl-c1">@time</span> printed above</pre></div>
<p dir="auto">also, using <code class="notranslate">for obj in arr</code> rather than <code class="notranslate">enumerate</code> does not allocate.</p>