ComponentArrays.jl icon indicating copy to clipboard operation
ComponentArrays.jl copied to clipboard

view vs getindex performance

Open klowrey opened this issue 3 years ago • 2 comments

I was replacing AxisArrays with ComponentArrays in a package (MuJoCo.jl) since AxisArrays kills the initial compile time despite having excellent run-time performance. ComponentArrays has a compatible interface that doesn't break user's code, but there are performance differences when using getindex:

image

As you can see, doing the getindex style access of the ComponentArray is much slower than the view, although from the source code I can't exactly tell why that would be the case since they should both be converting to Vals (which seems to be the slowdown). For some reason the conversion toval doesn't happen at compile-time for getindex could explain the slow-down?

While I can access the data as a property q.slider that doesn't work for multi-dimensional ComponentArrays which we have. I'll put a note in our docs about this, but was wondering if you had any insights as to what's going on. Thanks!

klowrey avatar Sep 23 '21 20:09 klowrey

Calling getindex on a ComponentArray slices the array, rather than views. So in this case, the performance hit is partially due to you allocating a new array with the slice. The behavior of ComponentArrays is to slice for getindex and view for getproperty. This behavior changed pretty recently (well, a few months ago). The old behavior was that getindex would view when one or more of the indices was a symbol and slice otherwise. It sounds like the view behavior is actually what you're expecting here, right? In that case, view or @view is probably the best choice.

If you do want to slice and it's too slow, though, you can try q[Val(:slider)]. That should make slices faster. I'm not sure why view is able to constant-fold the Val but getindex isn't.

jonniedie avatar Sep 23 '21 21:09 jonniedie

Yes I recommend to users to now do q[Val(:slider)] and it indeed is very quick. I guess my general question was indeed why Julia isn't constant-folding the Val in since a fixed Symbol should be as static as the Val of the symbol (in the same function). One thought is that Val(:slider) will call on the generated getindex function which has type-stable outputs while looking at @code_warntype seems to have some kind of instabilities...

I don't think I'm savvy enough with Julia to figure it out, but just wanted to know if you had some ideas.

klowrey avatar Sep 24 '21 22:09 klowrey