Bingo. You’re hitting what is frequently referred to as the splatting penalty. Splatting arguments into varargs functions like getindex can be allocation-free, but only the function inlines into the caller. Otherwise, Julia needs to allocate a tuple on the heap in order to pass the indices to getindex
. That’s where you’re seeing the bulk of the allocations come from with the more complicated versions of your object — the computation becomes complex enough that the indexing call no longer inlines. So you can add an inline annotation to the function to ensure it inlines and avoid the allocation.
Adding inline annotations to @generated
functions is also tricky. Doing the obvious things (@inline @generated function …
) doesn’t work because you’re actually annotating the generator function (and not the generated one). Instead, you can use the un-exported helper function to do this:
return :(Base.@_inline_meta; $ex)
That puts the inline annotation into the generated function. See Call-site splatting optimization · Issue #13359 · JuliaLang/julia · GitHub for more details.