StaticArrays.jl
StaticArrays.jl copied to clipboard
SVector sometimes allocates
This does not allocate
const v=[1]
const vl=length(v)
function g()
SVector{vl, Int}(v)
end
@timev g()
0.000001 seconds
elapsed time (ns): 769
gc time (ns): 0
bytes allocated: 0
pool allocs: 0
non-pool GC allocs: 0
minor collections: 0
full collections: 0
But this allocates:
const v=[1]
function g()
vl=length(v)
SVector{vl, Int}(v)
end
@timev g()
0.000017 seconds (10 allocations: 528 bytes)
elapsed time (ns): 17108
bytes allocated: 528
pool allocs: 10
1-element SVector{1, Int64} with indices SOneTo(1):
1
julia> @allocated g()
528
Using @SVector is not an option for me due to #1014
I believe this is more or less expected, since g is type unstable -- even if v is const, the length is not.
julia> @code_warntype g()
MethodInstance for g()
from g() in Main at REPL[5]:1
Arguments
#self#::Core.Const(g)
Locals
vl::Int64
Body::Any
1 ─ (vl = Main.length(Main.v))
│ %2 = Core.apply_type(Main.SVector, vl, Main.Int)::Type{SVector{_A, Int64}} where _A
│ %3 = (%2)(Main.v)::Any
└── return %3
@fredrikekre thank you for the quick reply. Can you think of any workaround? Any kind of function barrier?
You can pass around Val(length(v)) to get it to specialize the inner code.
@andyferris I still get allocations. Am I missing something? thanks
using StaticArrays
function createMVector(len::Val{L}) where {L}
return MVector{L, Int}((1 for i in 1:L))
end
const s=[1]
julia> @allocated createMVector(Val(length(s)))
14348930
julia> @allocated createMVector(Val(length(s)))
16