I have tried a number of things to convert an MVector to an SVector and they all result in various numbers of allocations and/or poor performance. My understanding is that an MVector is just a tuple wrapped in a struct. So… theoretically, couldn’t it run as fast as the same operation for a tuple?
Here’s an example:
function shorten_it(v, len)
return first(v, len) # v[1:len]
end
function test_tup()
len = rand(4:5)
v = (1:6...,)
@btime shorten_it($v, $len)
end
test_tup()
# 31.156 ns (1 allocation: 96 bytes)
function shorten_it_mv(v, len)
return SVector{len}(first(v.data, len))
end
function test_mv()
len = rand(4:5)
v = MVector(1:6...)
@btime shorten_it_mv($v, $len)
end
test_mv()
# 1.280 μs (11 allocations: 656 bytes)
Why is the MVector case slower?
I tried StaticArrays.sacollect which was much slower. I understand that whatever might use this type of function could probably be rewritten to use sacollect directly. That can get messy sometimes, and so I’d like to set that aside for this question.
I’m assuming it’s impossible to do this without at least 1 allocation because you can’t return variable length stack data from a method (stack pointer won’t know how much to move).
A case I have run into repeatedly: I know a relatively short max length of an array (maybe 8 or 16), but it is of variable length. For some cases, I suppose views might be the right answer (and that could get to 0 allocations). But for others, I’m guessing copying into an SVector/Tuple would be better overall.