Efficiency of push! on a Vector vs push on an SVector

Are there cases where it might be more efficient to use push with an SVector than to use push! with a Vector?

I have one benchmark below where push! is much more efficient:

using StaticArrays
using BenchmarkTools

function foo(x)
    y = SVector{0, eltype(x)}()
    for v in x
        y = push(y, v)
    end
    y
end

function bar(x)
    y = Vector{eltype(x)}()
    for v in x
        push!(y, v)
    end
    y
end

x = 1:50
julia> @btime foo($x);
  5.740 μs (50 allocations: 10.67 KiB)

julia> @btime bar($x);
  410.457 ns (6 allocations: 1.14 KiB)

SVector is only efficient when the length of the vector is known at compile time, because the length is a part of the type. If you have a runtime push! loop, where the compiler doesn’t know the number of loop iterations, using SVector will be type-unstable and hence slow.

(The reason why something like SVector is not the default array type in Julia is that they are much less versatile than Array … but for the specialized cases where SVector applies, they are fantastic.)

6 Likes